🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / app / src / main / java / com / geeksville / mesh / service / MeshService.kt
Displaying Raw • Download
app/src/main/java/com/geeksville/mesh/service/MeshService.kt ui_message_list (be3f882f) Text, 102.48 KB
T8b949e/*
* Copyright (c) 2025 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787com.geeksville.mesh.service
Tff7b72import T7ee787android.annotation.SuppressLint
Tff7b72import T7ee787android.app.Service
Tff7b72import T7ee787android.content.Context
Tff7b72import T7ee787android.content.Intent
Tff7b72import T7ee787android.content.pm.ServiceInfo
Tff7b72import T7ee787android.os.Build
Tff7b72import T7ee787android.os.IBinder
Tff7b72import T7ee787android.os.RemoteException
Tff7b72import T7ee787androidx.core.app.ServiceCompat
Tff7b72import T7ee787androidx.core.location.LocationCompat
Tff7b72import T7ee787com.geeksville.mesh.AdminProtos
Tff7b72import T7ee787com.geeksville.mesh.AppOnlyProtos
Tff7b72import T7ee787com.geeksville.mesh.BuildConfig
Tff7b72import T7ee787com.geeksville.mesh.ChannelProtos
Tff7b72import T7ee787com.geeksville.mesh.ConfigProtos
Tff7b72import T7ee787com.geeksville.mesh.CoroutineDispatchers
Tff7b72import T7ee787com.geeksville.mesh.DataPacket
Tff7b72import T7ee787com.geeksville.mesh.DeviceUIProtos
Tff7b72import T7ee787com.geeksville.mesh.IMeshService
Tff7b72import T7ee787com.geeksville.mesh.LocalOnlyProtos.LocalConfig
Tff7b72import T7ee787com.geeksville.mesh.LocalOnlyProtos.LocalModuleConfig
Tff7b72import T7ee787com.geeksville.mesh.MeshProtos
Tff7b72import T7ee787com.geeksville.mesh.MeshProtos.FromRadio.PayloadVariantCase
Tff7b72import T7ee787com.geeksville.mesh.MeshProtos.MeshPacket
Tff7b72import T7ee787com.geeksville.mesh.MeshProtos.ToRadio
Tff7b72import T7ee787com.geeksville.mesh.MeshUser
Tff7b72import T7ee787com.geeksville.mesh.MessageStatus
Tff7b72import T7ee787com.geeksville.mesh.ModuleConfigProtos
Tff7b72import T7ee787com.geeksville.mesh.MyNodeInfo
Tff7b72import T7ee787com.geeksville.mesh.NodeInfo
Tff7b72import T7ee787com.geeksville.mesh.PaxcountProtos
Tff7b72import T7ee787com.geeksville.mesh.Portnums
Tff7b72import T7ee787com.geeksville.mesh.Position
Tff7b72import T7ee787com.geeksville.mesh.R
Tff7b72import T7ee787com.geeksville.mesh.StoreAndForwardProtos
Tff7b72import T7ee787com.geeksville.mesh.TelemetryProtos
Tff7b72import T7ee787com.geeksville.mesh.TelemetryProtos.LocalStats
Tff7b72import T7ee787com.geeksville.mesh.XmodemProtos
Tff7b72import T7ee787com.geeksville.mesh.analytics.DataPair
Tff7b72import T7ee787com.geeksville.mesh.android.GeeksvilleApplication
Tff7b72import T7ee787com.geeksville.mesh.android.Logging
Tff7b72import T7ee787com.geeksville.mesh.android.hasLocationPermission
Tff7b72import T7ee787com.geeksville.mesh.android.prefs.MeshPrefs
Tff7b72import T7ee787com.geeksville.mesh.concurrent.handledLaunch
Tff7b72import T7ee787com.geeksville.mesh.copy
Tff7b72import T7ee787com.geeksville.mesh.database.MeshLogRepository
Tff7b72import T7ee787com.geeksville.mesh.database.PacketRepository
Tff7b72import T7ee787com.geeksville.mesh.database.entity.MeshLog
Tff7b72import T7ee787com.geeksville.mesh.database.entity.MyNodeEntity
Tff7b72import T7ee787com.geeksville.mesh.database.entity.NodeEntity
Tff7b72import T7ee787com.geeksville.mesh.database.entity.Packet
Tff7b72import T7ee787com.geeksville.mesh.database.entity.ReactionEntity
Tff7b72import T7ee787com.geeksville.mesh.fromRadio
Tff7b72import T7ee787com.geeksville.mesh.model.DeviceVersion
Tff7b72import T7ee787com.geeksville.mesh.model.NO_DEVICE_SELECTED
Tff7b72import T7ee787com.geeksville.mesh.model.Node
Tff7b72import T7ee787com.geeksville.mesh.model.getFullTracerouteResponse
Tff7b72import T7ee787com.geeksville.mesh.position
Tff7b72import T7ee787com.geeksville.mesh.repository.datastore.RadioConfigRepository
Tff7b72import T7ee787com.geeksville.mesh.repository.location.LocationRepository
Tff7b72import T7ee787com.geeksville.mesh.repository.network.MQTTRepository
Tff7b72import T7ee787com.geeksville.mesh.repository.radio.RadioInterfaceService
Tff7b72import T7ee787com.geeksville.mesh.repository.radio.RadioServiceConnectionState
Tff7b72import T7ee787com.geeksville.mesh.telemetry
Tff7b72import T7ee787com.geeksville.mesh.user
Tff7b72import T7ee787com.geeksville.mesh.util.anonymize
Tff7b72import T7ee787com.geeksville.mesh.util.ignoreException
Tff7b72import T7ee787com.geeksville.mesh.util.toOneLineString
Tff7b72import T7ee787com.geeksville.mesh.util.toPIIString
Tff7b72import T7ee787com.geeksville.mesh.util.toRemoteExceptions
Tff7b72import T7ee787com.google.protobuf.ByteString
Tff7b72import T7ee787com.google.protobuf.InvalidProtocolBufferException
Tff7b72import T7ee787dagger.Lazy
Tff7b72import T7ee787dagger.hilt.android.AndroidEntryPoint
Tff7b72import T7ee787kotlinx.coroutines.CancellationException
Tff7b72import T7ee787kotlinx.coroutines.CoroutineScope
Tff7b72import T7ee787kotlinx.coroutines.Dispatchers
Tff7b72import T7ee787kotlinx.coroutines.Job
Tff7b72import T7ee787kotlinx.coroutines.delay
Tff7b72import T7ee787kotlinx.coroutines.flow.MutableStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.StateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.asStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.catch
Tff7b72import T7ee787kotlinx.coroutines.flow.launchIn
Tff7b72import T7ee787kotlinx.coroutines.flow.onEach
Tff7b72import T7ee787java.util.Random
Tff7b72import T7ee787java.util.UUID
Tff7b72import T7ee787java.util.concurrent.ConcurrentHashMap
Tff7b72import T7ee787javax.inject.Inject
Tff7b72import T7ee787kotlin.math.absoluteValue
Tff7b72sealed Tff7b72class T56d364ServiceAction Tb4b4b4{
Tff7b72data Tff7b72class T56d364GetDeviceMetadataTb4b4b4(Tff7b72val Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4: Te6edf3ServiceActionTb4b4b4(Tb4b4b4)
Tff7b72data Tff7b72class T56d364FavoriteTb4b4b4(Tff7b72val Te6edf3nodeTb4b4b4: Te6edf3NodeTb4b4b4) Tb4b4b4: Te6edf3ServiceActionTb4b4b4(Tb4b4b4)
Tff7b72data Tff7b72class T56d364IgnoreTb4b4b4(Tff7b72val Te6edf3nodeTb4b4b4: Te6edf3NodeTb4b4b4) Tb4b4b4: Te6edf3ServiceActionTb4b4b4(Tb4b4b4)
Tff7b72data Tff7b72class T56d364ReactionTb4b4b4(Tff7b72val Te6edf3emojiTb4b4b4: Tffa657StringTb4b4b4, Tff7b72val Te6edf3replyIdTb4b4b4: Tffa657IntTb4b4b4, Tff7b72val Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4: Te6edf3ServiceActionTb4b4b4(Tb4b4b4)
Tff7b72data Tff7b72class T56d364AddSharedContactTb4b4b4(Tff7b72val Te6edf3contactTb4b4b4: Te6edf3AdminProtosTb4b4b4.Te6edf3SharedContactTb4b4b4) Tb4b4b4: Te6edf3ServiceActionTb4b4b4(Tb4b4b4)
Tb4b4b4}
T8b949e/**
* Handles all the communication with android apps. Also keeps an internal model of the network state.
*
* Note: this service will go away once all clients are unbound from it. Warning: do not override toString, it causes
* infinite recursion on some androids (because contextWrapper.getResources calls to string
*/
Tf0883e@AndroidEntryPoint
Tff7b72class T56d364MeshService Tb4b4b4:
Te6edf3ServiceTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3Logging Tb4b4b4{
Tf0883e@Inject Tff7b72lateinit Tff7b72var Te6edf3dispatchersTb4b4b4: Te6edf3CoroutineDispatchers
Tf0883e@Inject Tff7b72lateinit Tff7b72var Te6edf3packetRepositoryTb4b4b4: Te6edf3LazyTff7b72<Te6edf3PacketRepositoryTff7b72>
Tf0883e@Inject Tff7b72lateinit Tff7b72var Te6edf3meshLogRepositoryTb4b4b4: Te6edf3LazyTff7b72<Te6edf3MeshLogRepositoryTff7b72>
Tf0883e@Inject Tff7b72lateinit Tff7b72var Te6edf3radioInterfaceServiceTb4b4b4: Te6edf3RadioInterfaceService
Tf0883e@Inject Tff7b72lateinit Tff7b72var Te6edf3locationRepositoryTb4b4b4: Te6edf3LocationRepository
Tf0883e@Inject Tff7b72lateinit Tff7b72var Te6edf3radioConfigRepositoryTb4b4b4: Te6edf3RadioConfigRepository
Tf0883e@Inject Tff7b72lateinit Tff7b72var Te6edf3mqttRepositoryTb4b4b4: Te6edf3MQTTRepository
Tf0883e@Inject Tff7b72lateinit Tff7b72var Te6edf3serviceNotificationsTb4b4b4: Te6edf3MeshServiceNotifications
Tf0883e@Inject Tff7b72lateinit Tff7b72var Te6edf3meshPrefsTb4b4b4: Te6edf3MeshPrefs
Tff7b72private Tff7b72val Te6edf3tracerouteStartTimes Tff7b72= Te6edf3ConcurrentHashMapTff7b72<Tffa657IntTb4b4b4, Tffa657LongTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72companion Tff7b72object : T56d364Logging Tb4b4b4{
T8b949e// Intents broadcast by MeshService
Tff7b72private Tff7b72fun Td2a8ffactionReceivedTb4b4b4(Te6edf3portNumTb4b4b4: Tffa657StringTb4b4b4) Tff7b72= Ta5d6ff"Tffd700$Te6edf3prefixTa5d6ff.RECEIVED.Tffd700$Te6edf3portNumTa5d6ff"
T8b949e// generate a RECEIVED action filter string that includes either the portnumber as an int,
T8b949e// or preferably a
T8b949e// symbolic name from portnums.proto
Tff7b72fun Td2a8ffactionReceivedTb4b4b4(Te6edf3portNumTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72val Te6edf3portType Tff7b72= Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3forNumberTb4b4b4(Te6edf3portNumTb4b4b4)
Tff7b72val Te6edf3portStr Tff7b72= Te6edf3portTypeTff7b72?.Te6edf3toStringTb4b4b4(Tb4b4b4) Tff7b72?: Te6edf3portNumTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3actionReceivedTb4b4b4(Te6edf3portStrTb4b4b4)
Tb4b4b4}
Tff7b72const Tff7b72val Te6edf3ACTION_NODE_CHANGE Tff7b72= Ta5d6ff"Tffd700$Te6edf3prefixTa5d6ff.NODE_CHANGETa5d6ff"
Tff7b72const Tff7b72val Te6edf3ACTION_MESH_CONNECTED Tff7b72= Ta5d6ff"Tffd700$Te6edf3prefixTa5d6ff.MESH_CONNECTEDTa5d6ff"
Tff7b72const Tff7b72val Te6edf3ACTION_MESSAGE_STATUS Tff7b72= Ta5d6ff"Tffd700$Te6edf3prefixTa5d6ff.MESSAGE_STATUSTa5d6ff"
Tff7b72open Tff7b72class T56d364NodeNotFoundExceptionTb4b4b4(Te6edf3reasonTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4: Te6edf3ExceptionTb4b4b4(Te6edf3reasonTb4b4b4)
Tff7b72class T56d364InvalidNodeIdExceptionTb4b4b4(Te6edf3idTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4: Te6edf3NodeNotFoundExceptionTb4b4b4(Ta5d6ff"Ta5d6ffInvalid NodeId Tffd700$Te6edf3idTa5d6ff"Tb4b4b4)
Tff7b72class T56d364NodeNumNotFoundExceptionTb4b4b4(Te6edf3idTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4: Te6edf3NodeNotFoundExceptionTb4b4b4(Ta5d6ff"Ta5d6ffNodeNum not found Tffd700$Te6edf3idTa5d6ff"Tb4b4b4)
Tff7b72class T56d364IdNotFoundExceptionTb4b4b4(Te6edf3idTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4: Te6edf3NodeNotFoundExceptionTb4b4b4(Ta5d6ff"Ta5d6ffID not found Tffd700$Te6edf3idTa5d6ff"Tb4b4b4)
Tff7b72class T56d364NoDeviceConfigExceptionTb4b4b4(Te6edf3messageTb4b4b4: Tffa657String Tff7b72= Ta5d6ff"Ta5d6ffNo radio settings received (is our app too old?)Ta5d6ff"Tb4b4b4) Tb4b4b4:
Te6edf3RadioNotConnectedExceptionTb4b4b4(Te6edf3messageTb4b4b4)
T8b949e/**
* Talk to our running service and try to set a new device address. And then immediately call start on the
* service to possibly promote our service to be a foreground service.
*/
Tff7b72fun Td2a8ffchangeDeviceAddressTb4b4b4(Te6edf3contextTb4b4b4: Te6edf3ContextTb4b4b4, Te6edf3serviceTb4b4b4: Te6edf3IMeshServiceTb4b4b4, Te6edf3addressTb4b4b4: Tffa657String?Tb4b4b4) Tb4b4b4{
Te6edf3serviceTb4b4b4.Te6edf3setDeviceAddressTb4b4b4(Te6edf3addressTb4b4b4)
Te6edf3startServiceTb4b4b4(Te6edf3contextTb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffcreateIntentTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3IntentTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3setClassNameTb4b4b4(Ta5d6ff"Ta5d6ffcom.geeksville.meshTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffcom.geeksville.mesh.service.MeshServiceTa5d6ff"Tb4b4b4)
T8b949e/**
* The minimum firmware version we know how to talk to. We'll still be able to talk to 2.0 firmwares but only
* well enough to ask them to firmware update.
*/
Tff7b72val Te6edf3minDeviceVersion Tff7b72= Te6edf3DeviceVersionTb4b4b4(Te6edf3BuildConfigTb4b4b4.Te6edf3MIN_FW_VERSIONTb4b4b4)
Tff7b72val Te6edf3absoluteMinDeviceVersion Tff7b72= Te6edf3DeviceVersionTb4b4b4(Te6edf3BuildConfigTb4b4b4.Te6edf3ABS_MIN_FW_VERSIONTb4b4b4)
Tff7b72private Tff7b72const Tff7b72val Te6edf3CONFIG_ONLY_NONCE Tff7b72= T79c0ff6T79c0ff9T79c0ff4T79c0ff2T79c0ff0
Tff7b72private Tff7b72const Tff7b72val Te6edf3NODE_INFO_ONLY_NONCE Tff7b72= T79c0ff6T79c0ff9T79c0ff4T79c0ff2T79c0ff1
Tff7b72private Tff7b72const Tff7b72val Te6edf3CONFIG_WAIT_MS Tff7b72= T79c0ff2T79c0ff5T79c0ff0L
Tb4b4b4}
Tff7b72private Tff7b72var Te6edf3previousSummaryTb4b4b4: Tffa657String? Tff7b72= Tff7b72null
Tff7b72private Tff7b72var Te6edf3previousStatsTb4b4b4: Te6edf3LocalStats? Tff7b72= Tff7b72null
T8b949e// A mapping of receiver class name to package name - used for explicit broadcasts
Tff7b72private Tff7b72val Te6edf3clientPackages Tff7b72= Te6edf3mutableMapOfTff7b72<Tffa657StringTb4b4b4, Tffa657StringTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3serviceBroadcasts Tff7b72=
Te6edf3MeshServiceBroadcastsTb4b4b4(Tff7b72thisTb4b4b4, Te6edf3clientPackagesTb4b4b4) Tb4b4b4{
Te6edf3connectionStateTb4b4b4.Te6edf3also Tb4b4b4{ Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3setConnectionStateTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3packetHandlerTb4b4b4: Te6edf3PacketHandler Tff7b72by Te6edf3lazy Tb4b4b4{
Te6edf3PacketHandlerTb4b4b4(
Te6edf3packetRepository Tff7b72= Te6edf3packetRepositoryTb4b4b4,
Te6edf3serviceBroadcasts Tff7b72= Te6edf3serviceBroadcastsTb4b4b4,
Te6edf3radioInterfaceService Tff7b72= Te6edf3radioInterfaceServiceTb4b4b4,
Te6edf3meshLogRepository Tff7b72= Te6edf3meshLogRepositoryTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3serviceJob Tff7b72= Te6edf3JobTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3serviceScope Tff7b72= Te6edf3CoroutineScopeTb4b4b4(Te6edf3DispatchersTb4b4b4.Te6edf3IO Tff7b72+ Te6edf3serviceJobTb4b4b4)
Tff7b72private Tff7b72var Te6edf3connectionState Tff7b72= Te6edf3ConnectionStateTb4b4b4.Te6edf3DISCONNECTED
Tff7b72private Tff7b72var Te6edf3locationFlowTb4b4b4: Te6edf3Job? Tff7b72= Tff7b72null
Tff7b72private Tff7b72var Te6edf3mqttMessageFlowTb4b4b4: Te6edf3Job? Tff7b72= Tff7b72null
Tff7b72private Tff7b72val Te6edf3batteryPercentUnsupported Tff7b72= T79c0ff0.0
Tff7b72private Tff7b72val Te6edf3batteryPercentLowThreshold Tff7b72= T79c0ff2T79c0ff0
Tff7b72private Tff7b72val Te6edf3batteryPercentLowDivisor Tff7b72= T79c0ff5
Tff7b72private Tff7b72val Te6edf3batteryPercentCriticalThreshold Tff7b72= T79c0ff5
Tff7b72private Tff7b72val Te6edf3batteryPercentCooldownSeconds Tff7b72= T79c0ff1T79c0ff5T79c0ff0T79c0ff0
Tff7b72private Tff7b72val Te6edf3batteryPercentCooldownsTb4b4b4: Te6edf3HashMapTff7b72<Tffa657IntTb4b4b4, Tffa657LongTff7b72> Tff7b72= Te6edf3HashMapTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72fun Td2a8ffgetSenderNameTb4b4b4(Te6edf3packetTb4b4b4: Te6edf3DataPacket?Tb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72val Te6edf3name Tff7b72= Te6edf3nodeDBbyIDTff7b72[Te6edf3packetTff7b72?.Te6edf3fromTff7b72]Tff7b72?.Te6edf3userTff7b72?.Te6edf3longName
Tff7b72return Te6edf3name Tff7b72?: Te6edf3getStringTb4b4b4(Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3unknown_usernameTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3notificationSummary
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72=
Tff7b72when Tb4b4b4(Te6edf3connectionStateTb4b4b4) Tb4b4b4{
Te6edf3ConnectionStateTb4b4b4.Te6edf3CONNECTED Tff7b72-Tff7b72> Te6edf3getStringTb4b4b4(Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3connected_countTb4b4b4)Tb4b4b4.Te6edf3formatTb4b4b4(Te6edf3numOnlineNodesTb4b4b4)
Te6edf3ConnectionStateTb4b4b4.Te6edf3DISCONNECTED Tff7b72-Tff7b72> Te6edf3getStringTb4b4b4(Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3disconnectedTb4b4b4)
Te6edf3ConnectionStateTb4b4b4.Te6edf3DEVICE_SLEEP Tff7b72-Tff7b72> Te6edf3getStringTb4b4b4(Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3device_sleepingTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72var Te6edf3localStatsTelemetryTb4b4b4: Te6edf3TelemetryProtosTb4b4b4.Te6edf3TelemetryTff7b72? Tff7b72= Tff7b72null
Tff7b72private Tff7b72val Te6edf3localStatsTb4b4b4: Te6edf3LocalStats?
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3localStatsTelemetryTff7b72?.Te6edf3localStats
Tff7b72private Tff7b72val Te6edf3localStatsUpdatedAtMillisTb4b4b4: Tffa657Long?
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3localStatsTelemetryTff7b72?.Te6edf3timeTff7b72?.Te6edf3let Tb4b4b4{ Tffa657it Tff7b72* T79c0ff1T79c0ff0T79c0ff0T79c0ff0L Tb4b4b4}
T8b949e/** start our location requests (if they weren't already running) */
Tff7b72private Tff7b72fun Td2a8ffstartLocationRequestsTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// If we're already observing updates, don't register again
Tff7b72if Tb4b4b4(Te6edf3locationFlowTff7b72?.Te6edf3isActive Tff7b72=Tff7b72= Tff7b72trueTb4b4b4) Tff7b72return
Tf0883e@SuppressLintTb4b4b4(Ta5d6ff"Ta5d6ffMissingPermissionTa5d6ff"Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3hasLocationPermissionTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3locationFlow Tff7b72=
Te6edf3locationRepository
Tb4b4b4.Te6edf3getLocationsTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3onEach Tb4b4b4{ Te6edf3location Tff7b72-Tff7b72>
Te6edf3sendPositionTb4b4b4(
Te6edf3position Tb4b4b4{
Te6edf3latitudeI Tff7b72= Te6edf3PositionTb4b4b4.Te6edf3degITb4b4b4(Te6edf3locationTb4b4b4.Te6edf3latitudeTb4b4b4)
Te6edf3longitudeI Tff7b72= Te6edf3PositionTb4b4b4.Te6edf3degITb4b4b4(Te6edf3locationTb4b4b4.Te6edf3longitudeTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3LocationCompatTb4b4b4.Te6edf3hasMslAltitudeTb4b4b4(Te6edf3locationTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3altitude Tff7b72= Te6edf3LocationCompatTb4b4b4.Te6edf3getMslAltitudeMetersTb4b4b4(Te6edf3locationTb4b4b4)Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)
Tb4b4b4}
Te6edf3altitudeHae Tff7b72= Te6edf3locationTb4b4b4.Te6edf3altitudeTb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)
Te6edf3time Tff7b72= Tb4b4b4(Te6edf3locationTb4b4b4.Te6edf3time Tff7b72/ T79c0ff1T79c0ff0T79c0ff0T79c0ff0Tb4b4b4)Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)
Te6edf3groundSpeed Tff7b72= Te6edf3locationTb4b4b4.Te6edf3speedTb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)
Te6edf3groundTrack Tff7b72= Te6edf3locationTb4b4b4.Te6edf3bearingTb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)
Te6edf3locationSource Tff7b72= Te6edf3MeshProtosTb4b4b4.Te6edf3PositionTb4b4b4.Te6edf3LocSourceTb4b4b4.Te6edf3LOC_EXTERNAL
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3serviceScopeTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffstopLocationRequestsTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3locationFlowTff7b72?.Te6edf3isActive Tff7b72=Tff7b72= Tff7b72trueTb4b4b4) Tb4b4b4{
Te6edf3infoTb4b4b4(Ta5d6ff"Ta5d6ffStopping location requestsTa5d6ff"Tb4b4b4)
Te6edf3locationFlowTff7b72?.Te6edf3cancelTb4b4b4(Tb4b4b4)
Te6edf3locationFlow Tff7b72= Tff7b72null
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffshowAlertNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4, Te6edf3dataPacketTb4b4b4: Te6edf3DataPacketTb4b4b4) Tb4b4b4{
Te6edf3serviceNotificationsTb4b4b4.Te6edf3showAlertNotificationTb4b4b4(
Te6edf3contactKeyTb4b4b4,
Te6edf3getSenderNameTb4b4b4(Te6edf3dataPacketTb4b4b4)Tb4b4b4,
Te6edf3dataPacketTb4b4b4.Te6edf3alert Tff7b72?: Te6edf3getStringTb4b4b4(Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3critical_alertTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffupdateMessageNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4, Te6edf3dataPacketTb4b4b4: Te6edf3DataPacketTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3messageTb4b4b4: Tffa657String Tff7b72=
Tff7b72when Tb4b4b4(Te6edf3dataPacketTb4b4b4.Te6edf3dataTypeTb4b4b4) Tb4b4b4{
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3TEXT_MESSAGE_APP_VALUE Tff7b72-Tff7b72> Te6edf3dataPacketTb4b4b4.Te6edf3textTff7b72!!
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3WAYPOINT_APP_VALUE Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3getStringTb4b4b4(Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3waypoint_receivedTb4b4b4, Te6edf3dataPacketTb4b4b4.Te6edf3waypointTff7b72!!Tb4b4b4.Te6edf3nameTb4b4b4)
Tb4b4b4}
Tff7b72else Tff7b72-Tff7b72> Tff7b72return
Tb4b4b4}
Te6edf3serviceNotificationsTb4b4b4.Te6edf3updateMessageNotificationTb4b4b4(
Te6edf3contactKeyTb4b4b4,
Te6edf3getSenderNameTb4b4b4(Te6edf3dataPacketTb4b4b4)Tb4b4b4,
Te6edf3messageTb4b4b4,
Te6edf3isBroadcast Tff7b72= Te6edf3dataPacketTb4b4b4.Te6edf3to Tff7b72=Tff7b72= Te6edf3DataPacketTb4b4b4.Te6edf3ID_BROADCASTTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffonCreateTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72superTb4b4b4.Te6edf3onCreateTb4b4b4(Tb4b4b4)
Te6edf3_lastAddressTb4b4b4.Te6edf3value Tff7b72= Te6edf3meshPrefsTb4b4b4.Te6edf3deviceAddress Tff7b72?: Te6edf3NO_DEVICE_SELECTED
Te6edf3infoTb4b4b4(Ta5d6ff"Ta5d6ffCreating mesh serviceTa5d6ff"Tb4b4b4)
Te6edf3serviceNotificationsTb4b4b4.Te6edf3initChannelsTb4b4b4(Tb4b4b4)
T8b949e// Switch to the IO thread
Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{ Te6edf3radioInterfaceServiceTb4b4b4.Te6edf3connectTb4b4b4(Tb4b4b4) Tb4b4b4}
Te6edf3radioInterfaceServiceTb4b4b4.Te6edf3connectionStateTb4b4b4.Te6edf3onEachTb4b4b4(Tff7b72::Te6edf3onRadioConnectionStateTb4b4b4)Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3serviceScopeTb4b4b4)
Te6edf3radioInterfaceServiceTb4b4b4.Te6edf3receivedDataTb4b4b4.Te6edf3onEachTb4b4b4(Tff7b72::Te6edf3onReceiveFromRadioTb4b4b4)Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3serviceScopeTb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3localConfigFlowTb4b4b4.Te6edf3onEach Tb4b4b4{ Te6edf3localConfig Tff7b72= Tffa657it Tb4b4b4}Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3serviceScopeTb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3moduleConfigFlowTb4b4b4.Te6edf3onEach Tb4b4b4{ Te6edf3moduleConfig Tff7b72= Tffa657it Tb4b4b4}Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3serviceScopeTb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3channelSetFlowTb4b4b4.Te6edf3onEach Tb4b4b4{ Te6edf3channelSet Tff7b72= Tffa657it Tb4b4b4}Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3serviceScopeTb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3serviceActionTb4b4b4.Te6edf3onEachTb4b4b4(Tff7b72::Te6edf3onServiceActionTb4b4b4)Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3serviceScopeTb4b4b4)
Te6edf3loadSettingsTb4b4b4(Tb4b4b4) T8b949e// Load our last known node DB
T8b949e// the rest of our init will happen once we are in radioConnection.onServiceConnected
Tb4b4b4}
T8b949e/** If someone binds to us, this will be called after on create */
Tff7b72override Tff7b72fun Td2a8ffonBindTb4b4b4(Te6edf3intentTb4b4b4: Te6edf3Intent?Tb4b4b4)Tb4b4b4: Te6edf3IBinder Tff7b72= Te6edf3binder
T8b949e/**
* Called when the service is started or restarted. This method manages the foreground state of the service.
*
* It attempts to start the service in the foreground with a notification. If `startForeground` fails, for example,
* due to a `SecurityException` on Android 13+ because the `POST_NOTIFICATIONS` permission is missing, it logs an
* error* and returns `START_NOT_STICKY` to prevent the service from becoming sticky in a broken state.
*
* If the service is not intended to be in the foreground (e.g., no device is connected), it stops the foreground
* state and returns `START_NOT_STICKY`. Otherwise, it returns `START_STICKY`.
*
* @param intent The Intent supplied to `startService(Intent)`, as modified by the system.
* @param flags Additional data about this start request.
* @param startId A unique integer representing this specific request to start.
* @return The return value indicates what semantics the system should use for the service's current started state.
* See [Service.onStartCommand] for details.
*/
Tff7b72override Tff7b72fun Td2a8ffonStartCommandTb4b4b4(Te6edf3intentTb4b4b4: Te6edf3Intent?Tb4b4b4, Te6edf3flagsTb4b4b4: Tffa657IntTb4b4b4, Te6edf3startIdTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Tffa657Int Tb4b4b4{
Tff7b72val Te6edf3a Tff7b72= Te6edf3radioInterfaceServiceTb4b4b4.Te6edf3getBondedDeviceAddressTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3wantForeground Tff7b72= Te6edf3a Tff7b72!Tff7b72= Tff7b72null Tff7b72&Tff7b72& Te6edf3a Tff7b72!Tff7b72= Te6edf3NO_DEVICE_SELECTED
Te6edf3infoTb4b4b4(Ta5d6ff"Ta5d6ffRequesting foreground service=Tffd700$Te6edf3wantForegroundTa5d6ff"Tb4b4b4)
T8b949e// We always start foreground because that's how our service is always started (if we didn't
T8b949e// then android would
T8b949e// kill us)
T8b949e// but if we don't really need foreground we immediately stop it.
Tff7b72val Te6edf3notification Tff7b72= Te6edf3serviceNotificationsTb4b4b4.Te6edf3updateServiceStateNotificationTb4b4b4(Te6edf3notificationSummaryTb4b4b4)
Tff7b72try Tb4b4b4{
Te6edf3ServiceCompatTb4b4b4.Te6edf3startForegroundTb4b4b4(
Tff7b72thisTb4b4b4,
Te6edf3MeshServiceNotificationsTb4b4b4.Te6edf3SERVICE_NOTIFY_IDTb4b4b4,
Te6edf3notificationTb4b4b4,
Tff7b72if Tb4b4b4(Te6edf3androidTb4b4b4.Te6edf3osTb4b4b4.Te6edf3BuildTb4b4b4.Te6edf3VERSIONTb4b4b4.Te6edf3SDK_INT Tff7b72>Tff7b72= Te6edf3androidTb4b4b4.Te6edf3osTb4b4b4.Te6edf3BuildTb4b4b4.Te6edf3VERSION_CODESTb4b4b4.Te6edf3QTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3hasLocationPermissionTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3ServiceInfoTb4b4b4.Te6edf3FOREGROUND_SERVICE_TYPE_MANIFEST
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3ServiceInfoTb4b4b4.Te6edf3FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
T79c0ff0
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3SecurityExceptionTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3BuildTb4b4b4.Te6edf3VERSIONTb4b4b4.Te6edf3SDK_INT Tff7b72>Tff7b72= Te6edf3BuildTb4b4b4.Te6edf3VERSION_CODESTb4b4b4.Te6edf3TIRAMISUTb4b4b4) Tb4b4b4{
Te6edf3errormsgTb4b4b4(
Ta5d6ff"Ta5d6ffstartForeground failed, likely due to missing POST_NOTIFICATIONS permission on Android 13+Ta5d6ff"Tb4b4b4,
Te6edf3exTb4b4b4,
Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3errormsgTb4b4b4(Ta5d6ff"Ta5d6ffstartForeground failedTa5d6ff"Tb4b4b4, Te6edf3exTb4b4b4)
Tb4b4b4}
Tff7b72return Te6edf3START_NOT_STICKY
Tb4b4b4}
Tff7b72return Tff7b72if Tb4b4b4(Tff7b72!Te6edf3wantForegroundTb4b4b4) Tb4b4b4{
Te6edf3ServiceCompatTb4b4b4.Te6edf3stopForegroundTb4b4b4(Tff7b72thisTb4b4b4, Te6edf3ServiceCompatTb4b4b4.Te6edf3STOP_FOREGROUND_REMOVETb4b4b4)
Te6edf3START_NOT_STICKY
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3START_STICKY
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffonDestroyTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3infoTb4b4b4(Ta5d6ff"Ta5d6ffDestroying mesh serviceTa5d6ff"Tb4b4b4)
T8b949e// Make sure we aren't using the notification first
Te6edf3ServiceCompatTb4b4b4.Te6edf3stopForegroundTb4b4b4(Tff7b72thisTb4b4b4, Te6edf3ServiceCompatTb4b4b4.Te6edf3STOP_FOREGROUND_REMOVETb4b4b4)
Tff7b72superTb4b4b4.Te6edf3onDestroyTb4b4b4(Tb4b4b4)
Te6edf3serviceJobTb4b4b4.Te6edf3cancelTb4b4b4(Tb4b4b4)
Tb4b4b4}
T8b949e//
T8b949e// BEGINNING OF MODEL - FIXME, move elsewhere
T8b949e//
Tff7b72private Tff7b72fun Td2a8ffloadSettingsTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
Te6edf3discardNodeDBTb4b4b4(Tb4b4b4) T8b949e// Get rid of any old state
Te6edf3myNodeInfo Tff7b72= Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3myNodeInfoTb4b4b4.Te6edf3value
Te6edf3nodeDBbyNodeNumTb4b4b4.Te6edf3putAllTb4b4b4(Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3getNodeDBbyNumTb4b4b4(Tb4b4b4)Tb4b4b4)
T8b949e// Note: we do not haveNodeDB = true because that means we've got a valid db from a real
T8b949e// device (rather than
T8b949e// this possibly stale hint)
Tb4b4b4}
T8b949e/** discard entire node db & message state - used when downloading a new db from the device */
Tff7b72private Tff7b72fun Td2a8ffdiscardNodeDBTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffDiscarding NodeDBTa5d6ff"Tb4b4b4)
Te6edf3myNodeInfo Tff7b72= Tff7b72null
Te6edf3nodeDBbyNodeNumTb4b4b4.Te6edf3clearTb4b4b4(Tb4b4b4)
Te6edf3haveNodeDB Tff7b72= Tff7b72false
Tb4b4b4}
Tff7b72private Tff7b72var Te6edf3myNodeInfoTb4b4b4: Te6edf3MyNodeEntity? Tff7b72= Tff7b72null
Tff7b72private Tff7b72val Te6edf3configTotal Tff7b72by Te6edf3lazy Tb4b4b4{ Te6edf3ConfigProtosTb4b4b4.Te6edf3ConfigTb4b4b4.Te6edf3getDescriptorTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3size Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3moduleTotal Tff7b72by Te6edf3lazy Tb4b4b4{ Te6edf3ModuleConfigProtosTb4b4b4.Te6edf3ModuleConfigTb4b4b4.Te6edf3getDescriptorTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3fieldsTb4b4b4.Te6edf3size Tb4b4b4}
Tff7b72private Tff7b72var Te6edf3sessionPasskeyTb4b4b4: Te6edf3ByteString Tff7b72= Te6edf3ByteStringTb4b4b4.Te6edf3EMPTY
Tff7b72private Tff7b72var Te6edf3localConfigTb4b4b4: Te6edf3LocalConfig Tff7b72= Te6edf3LocalConfigTb4b4b4.Te6edf3getDefaultInstanceTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72var Te6edf3moduleConfigTb4b4b4: Te6edf3LocalModuleConfig Tff7b72= Te6edf3LocalModuleConfigTb4b4b4.Te6edf3getDefaultInstanceTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72var Te6edf3channelSetTb4b4b4: Te6edf3AppOnlyProtosTb4b4b4.Te6edf3ChannelSet Tff7b72= Te6edf3AppOnlyProtosTb4b4b4.Te6edf3ChannelSetTb4b4b4.Te6edf3getDefaultInstanceTb4b4b4(Tb4b4b4)
T8b949e// True after we've done our initial node db init
Tf0883e@Volatile Tff7b72private Tff7b72var Te6edf3haveNodeDB Tff7b72= Tff7b72false
T8b949e// The database of active nodes, index is the node number
Tff7b72private Tff7b72val Te6edf3nodeDBbyNodeNum Tff7b72= Te6edf3ConcurrentHashMapTff7b72<Tffa657IntTb4b4b4, Te6edf3NodeEntityTff7b72>Tb4b4b4(Tb4b4b4)
T8b949e// The database of active nodes, index is the node user ID string
T8b949e// NOTE: some NodeInfos might be in only nodeDBbyNodeNum (because we don't yet know an ID).
Tff7b72private Tff7b72val Te6edf3nodeDBbyID
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3nodeDBbyNodeNumTb4b4b4.Te6edf3mapKeys Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3userTb4b4b4.Te6edf3id Tb4b4b4}
T8b949e//
T8b949e// END OF MODEL
T8b949e//
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffUnusedPrivateMemberTa5d6ff"Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3deviceVersion
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3DeviceVersionTb4b4b4(Te6edf3myNodeInfoTff7b72?.Te6edf3firmwareVersion Tff7b72?: Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffUnusedPrivateMemberTa5d6ff"Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3appVersion
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3BuildConfigTb4b4b4.Te6edf3VERSION_CODE
Tff7b72private Tff7b72val Te6edf3minAppVersion
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3myNodeInfoTff7b72?.Te6edf3minAppVersion Tff7b72?: T79c0ff0
T8b949e// Map a nodenum to a node, or throw an exception if not found
Tff7b72private Tff7b72fun Td2a8fftoNodeInfoTb4b4b4(Te6edf3nTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3nodeDBbyNodeNumTff7b72[Te6edf3nTff7b72] Tff7b72?: Tff7b72throw Te6edf3NodeNumNotFoundExceptionTb4b4b4(Te6edf3nTb4b4b4)
T8b949e/**
* Map a nodeNum to the nodeId string If we have a NodeInfo for this ID we prefer to return the string ID inside the
* user record. but some nodes might not have a user record at all (because not yet received), in that case, we
* return a hex version of the ID just based on the number
*/
Tff7b72private Tff7b72fun Td2a8fftoNodeIDTb4b4b4(Te6edf3nTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Tffa657String Tff7b72= Tff7b72if Tb4b4b4(Te6edf3n Tff7b72=Tff7b72= Te6edf3DataPacketTb4b4b4.Te6edf3NODENUM_BROADCASTTb4b4b4) Tb4b4b4{
Te6edf3DataPacketTb4b4b4.Te6edf3ID_BROADCAST
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3nodeDBbyNodeNumTff7b72[Te6edf3nTff7b72]Tff7b72?.Te6edf3userTff7b72?.Te6edf3id Tff7b72?: Te6edf3DataPacketTb4b4b4.Te6edf3nodeNumToDefaultIdTb4b4b4(Te6edf3nTb4b4b4)
Tb4b4b4}
T8b949e// given a nodeNum, return a db entry - creating if necessary
Tff7b72private Tff7b72fun Td2a8ffgetOrCreateNodeInfoTb4b4b4(Te6edf3nTb4b4b4: Tffa657IntTb4b4b4, Te6edf3channelTb4b4b4: Tffa657Int Tff7b72= T79c0ff0Tb4b4b4) Tff7b72= Te6edf3nodeDBbyNodeNumTb4b4b4.Te6edf3getOrPutTb4b4b4(Te6edf3nTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3userId Tff7b72= Te6edf3DataPacketTb4b4b4.Te6edf3nodeNumToDefaultIdTb4b4b4(Te6edf3nTb4b4b4)
Tff7b72val Te6edf3defaultUser Tff7b72= Te6edf3user Tb4b4b4{
Te6edf3id Tff7b72= Te6edf3userId
Te6edf3longName Tff7b72= Ta5d6ff"Ta5d6ffMeshtastic Tffd700${Te6edf3userIdTb4b4b4.Te6edf3takeLastTb4b4b4(Te6edf3n Tff7b72= T79c0ff4Tb4b4b4)Tffd700}Ta5d6ff"
Te6edf3shortName Tff7b72= Te6edf3userIdTb4b4b4.Te6edf3takeLastTb4b4b4(Te6edf3n Tff7b72= T79c0ff4Tb4b4b4)
Te6edf3hwModel Tff7b72= Te6edf3MeshProtosTb4b4b4.Te6edf3HardwareModelTb4b4b4.Te6edf3UNSET
Tb4b4b4}
Te6edf3NodeEntityTb4b4b4(Te6edf3num Tff7b72= Te6edf3nTb4b4b4, Te6edf3user Tff7b72= Te6edf3defaultUserTb4b4b4, Te6edf3longName Tff7b72= Te6edf3defaultUserTb4b4b4.Te6edf3longNameTb4b4b4, Te6edf3channel Tff7b72= Te6edf3channelTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3hexIdRegex Tff7b72= Ta5d6ff"""Ta5d6ff\Ta5d6ff!([0-9A-Fa-f]+)Ta5d6ff"""Tb4b4b4.Te6edf3toRegexTb4b4b4(Tb4b4b4)
T8b949e// Map a userid to a node/ node num, or throw an exception if not found
T8b949e// We prefer to find nodes based on their assigned IDs, but if no ID has been assigned to a
T8b949e// node, we can also find
T8b949e// it based on node number
Tff7b72private Tff7b72fun Td2a8fftoNodeInfoTb4b4b4(Te6edf3idTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3NodeEntity Tb4b4b4{
T8b949e// If this is a valid hexaddr will be !null
Tff7b72val Te6edf3hexStr Tff7b72= Te6edf3hexIdRegexTb4b4b4.Te6edf3matchEntireTb4b4b4(Te6edf3idTb4b4b4)Tff7b72?.Te6edf3groupsTff7b72?.Te6edf3getTb4b4b4(T79c0ff1Tb4b4b4)Tff7b72?.Te6edf3value
Tff7b72return Te6edf3nodeDBbyIDTff7b72[Te6edf3idTff7b72]
Tff7b72?: Tff7b72when Tb4b4b4{
Te6edf3id Tff7b72=Tff7b72= Te6edf3DataPacketTb4b4b4.Te6edf3ID_LOCAL Tff7b72-Tff7b72> Te6edf3toNodeInfoTb4b4b4(Te6edf3myNodeNumTb4b4b4)
Te6edf3hexStr Tff7b72!Tff7b72= Tff7b72null Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72val Te6edf3n Tff7b72= Te6edf3hexStrTb4b4b4.Te6edf3toLongTb4b4b4(T79c0ff1T79c0ff6Tb4b4b4)Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)
Te6edf3nodeDBbyNodeNumTff7b72[Te6edf3nTff7b72] Tff7b72?: Tff7b72throw Te6edf3IdNotFoundExceptionTb4b4b4(Te6edf3idTb4b4b4)
Tb4b4b4}
Tff7b72else Tff7b72-Tff7b72> Tff7b72throw Te6edf3InvalidNodeIdExceptionTb4b4b4(Te6edf3idTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffgetUserNameTb4b4b4(Te6edf3numTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Tffa657String Tff7b72= Te6edf3withTb4b4b4(Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3getUserTb4b4b4(Te6edf3numTb4b4b4)Tb4b4b4) Tb4b4b4{ Ta5d6ff"Tffd700$Te6edf3longNameTa5d6ff (Tffd700$Te6edf3shortNameTa5d6ff)Ta5d6ff" Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3numNodes
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3nodeDBbyNodeNumTb4b4b4.Te6edf3size
T8b949e/** How many nodes are currently online (including our local node) */
Tff7b72private Tff7b72val Te6edf3numOnlineNodes
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3nodeDBbyNodeNumTb4b4b4.Te6edf3valuesTb4b4b4.Te6edf3count Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3isOnline Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8fftoNodeNumTb4b4b4(Te6edf3idTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Tffa657Int Tff7b72= Tff7b72when Tb4b4b4(Te6edf3idTb4b4b4) Tb4b4b4{
Te6edf3DataPacketTb4b4b4.Te6edf3ID_BROADCAST Tff7b72-Tff7b72> Te6edf3DataPacketTb4b4b4.Te6edf3NODENUM_BROADCAST
Te6edf3DataPacketTb4b4b4.Te6edf3ID_LOCAL Tff7b72-Tff7b72> Te6edf3myNodeNum
Tff7b72else Tff7b72-Tff7b72> Te6edf3toNodeInfoTb4b4b4(Te6edf3idTb4b4b4)Tb4b4b4.Te6edf3num
Tb4b4b4}
T8b949e// A helper function that makes it easy to update node info objects
Tff7b72private Tff7b72inline Tff7b72fun Td2a8ffupdateNodeInfoTb4b4b4(
Te6edf3nodeNumTb4b4b4: Tffa657IntTb4b4b4,
Te6edf3withBroadcastTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72trueTb4b4b4,
Te6edf3channelTb4b4b4: Tffa657Int Tff7b72= T79c0ff0Tb4b4b4,
Te6edf3crossinline Te6edf3updateFnTb4b4b4: Tb4b4b4(Te6edf3NodeEntityTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4,
Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3info Tff7b72= Te6edf3getOrCreateNodeInfoTb4b4b4(Te6edf3nodeNumTb4b4b4, Te6edf3channelTb4b4b4)
Te6edf3updateFnTb4b4b4(Te6edf3infoTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3infoTb4b4b4.Te6edf3userTb4b4b4.Te6edf3idTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3haveNodeDBTb4b4b4) Tb4b4b4{
Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{ Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3upsertTb4b4b4(Te6edf3infoTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3withBroadcastTb4b4b4) Tb4b4b4{
Te6edf3serviceBroadcastsTb4b4b4.Te6edf3broadcastNodeChangeTb4b4b4(Te6edf3infoTb4b4b4.Te6edf3toNodeInfoTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
T8b949e// My node num
Tff7b72private Tff7b72val Te6edf3myNodeNum
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3myNodeInfoTff7b72?.Te6edf3myNodeNum Tff7b72?: Tff7b72throw Te6edf3RadioNotConnectedExceptionTb4b4b4(Ta5d6ff"Ta5d6ffWe don't yet have our myNodeInfoTa5d6ff"Tb4b4b4)
T8b949e// My node ID string
Tff7b72private Tff7b72val Te6edf3myNodeID
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3toNodeIDTb4b4b4(Te6edf3myNodeNumTb4b4b4)
T8b949e// Admin channel index
Tff7b72private Tff7b72val Te6edf3MeshPacketTb4b4b4.Te6edf3BuilderTb4b4b4.Te6edf3adminChannelIndexTb4b4b4: Tffa657Int
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72=
Tff7b72when Tb4b4b4{
Te6edf3myNodeNum Tff7b72=Tff7b72= Te6edf3to Tff7b72-Tff7b72> T79c0ff0
Te6edf3nodeDBbyNodeNumTff7b72[Te6edf3myNodeNumTff7b72]Tff7b72?.Te6edf3hasPKC Tff7b72=Tff7b72= Tff7b72true Tff7b72&Tff7b72& Te6edf3nodeDBbyNodeNumTff7b72[Te6edf3toTff7b72]Tff7b72?.Te6edf3hasPKC Tff7b72=Tff7b72= Tff7b72true Tff7b72-Tff7b72>
Te6edf3DataPacketTb4b4b4.Te6edf3PKC_CHANNEL_INDEX
Tff7b72else Tff7b72-Tff7b72>
Te6edf3channelSetTb4b4b4.Te6edf3settingsListTb4b4b4.Te6edf3indexOfFirst Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3nameTb4b4b4.Te6edf3equalsTb4b4b4(Ta5d6ff"Ta5d6ffadminTa5d6ff"Tb4b4b4, Te6edf3ignoreCase Tff7b72= Tff7b72trueTb4b4b4) Tb4b4b4}Tb4b4b4.Te6edf3coerceAtLeastTb4b4b4(T79c0ff0Tb4b4b4)
Tb4b4b4}
T8b949e// Generate a new mesh packet builder with our node as the sender, and the specified node num
Tff7b72private Tff7b72fun Td2a8ffnewMeshPacketToTb4b4b4(Te6edf3idNumTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3MeshPacketTb4b4b4.Te6edf3newBuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3myNodeInfo Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72throw Te6edf3RadioNotConnectedExceptionTb4b4b4(Tb4b4b4)
Tb4b4b4}
Te6edf3from Tff7b72= T79c0ff0 T8b949e// don't add myNodeNum
Te6edf3to Tff7b72= Te6edf3idNum
Tb4b4b4}
T8b949e/**
* Generate a new mesh packet builder with our node as the sender, and the specified recipient
*
* If id is null we assume a broadcast message
*/
Tff7b72private Tff7b72fun Td2a8ffnewMeshPacketToTb4b4b4(Te6edf3idTb4b4b4: Tffa657StringTb4b4b4) Tff7b72= Te6edf3newMeshPacketToTb4b4b4(Te6edf3toNodeNumTb4b4b4(Te6edf3idTb4b4b4)Tb4b4b4)
T8b949e/** Helper to make it easy to build a subpacket in the proper protobufs */
Tff7b72private Tff7b72fun Te6edf3MeshPacketTb4b4b4.Td2a8ffBuilderTb4b4b4.Te6edf3buildMeshPacketTb4b4b4(
Te6edf3wantAckTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72falseTb4b4b4,
Te6edf3idTb4b4b4: Tffa657Int Tff7b72= Te6edf3generatePacketIdTb4b4b4(Tb4b4b4)Tb4b4b4, T8b949e// always assign a packet ID if we didn't already have one
Te6edf3hopLimitTb4b4b4: Tffa657Int Tff7b72= Te6edf3localConfigTb4b4b4.Te6edf3loraTb4b4b4.Te6edf3hopLimitTb4b4b4,
Te6edf3channelTb4b4b4: Tffa657Int Tff7b72= T79c0ff0Tb4b4b4,
Te6edf3priorityTb4b4b4: Te6edf3MeshPacketTb4b4b4.Te6edf3Priority Tff7b72= Te6edf3MeshPacketTb4b4b4.Te6edf3PriorityTb4b4b4.Te6edf3UNSETTb4b4b4,
Te6edf3initFnTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3DataTb4b4b4.Te6edf3BuilderTb4b4b4.Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3MeshPacket Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3wantAck Tff7b72= Te6edf3wantAck
Tff7b72thisTb4b4b4.Te6edf3id Tff7b72= Te6edf3id
Tff7b72thisTb4b4b4.Te6edf3hopLimit Tff7b72= Te6edf3hopLimit
Tff7b72thisTb4b4b4.Te6edf3priority Tff7b72= Te6edf3priority
Te6edf3decoded Tff7b72= Te6edf3MeshProtosTb4b4b4.Te6edf3DataTb4b4b4.Te6edf3newBuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3also Tb4b4b4{ Te6edf3initFnTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3channel Tff7b72=Tff7b72= Te6edf3DataPacketTb4b4b4.Te6edf3PKC_CHANNEL_INDEXTb4b4b4) Tb4b4b4{
Te6edf3pkiEncrypted Tff7b72= Tff7b72true
Te6edf3nodeDBbyNodeNumTff7b72[Te6edf3toTff7b72]Tff7b72?.Te6edf3userTff7b72?.Te6edf3publicKeyTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3publicKey Tff7b72-Tff7b72> Tff7b72thisTb4b4b4.Te6edf3publicKey Tff7b72= Te6edf3publicKey Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3channel Tff7b72= Te6edf3channel
Tb4b4b4}
Tff7b72return Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
T8b949e/** Helper to make it easy to build a subpacket in the proper protobufs */
Tff7b72private Tff7b72fun Te6edf3MeshPacketTb4b4b4.Td2a8ffBuilderTb4b4b4.Te6edf3buildAdminPacketTb4b4b4(
Te6edf3idTb4b4b4: Tffa657Int Tff7b72= Te6edf3generatePacketIdTb4b4b4(Tb4b4b4)Tb4b4b4, T8b949e// always assign a packet ID if we didn't already have one
Te6edf3wantResponseTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72falseTb4b4b4,
Te6edf3initFnTb4b4b4: Te6edf3AdminProtosTb4b4b4.Te6edf3AdminMessageTb4b4b4.Te6edf3BuilderTb4b4b4.Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3MeshPacket Tff7b72=
Te6edf3buildMeshPacketTb4b4b4(Te6edf3id Tff7b72= Te6edf3idTb4b4b4, Te6edf3wantAck Tff7b72= Tff7b72trueTb4b4b4, Te6edf3channel Tff7b72= Te6edf3adminChannelIndexTb4b4b4, Te6edf3priority Tff7b72= Te6edf3MeshPacketTb4b4b4.Te6edf3PriorityTb4b4b4.Te6edf3RELIABLETb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3wantResponse Tff7b72= Te6edf3wantResponse
Te6edf3portnumValue Tff7b72= Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3ADMIN_APP_VALUE
Te6edf3payload Tff7b72=
Te6edf3AdminProtosTb4b4b4.Te6edf3AdminMessageTb4b4b4.Te6edf3newBuilderTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3also Tb4b4b4{
Te6edf3initFnTb4b4b4(Tffa657itTb4b4b4)
Tffa657itTb4b4b4.Te6edf3sessionPasskey Tff7b72= Te6edf3sessionPasskey
Tb4b4b4}
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3toByteStringTb4b4b4(Tb4b4b4)
Tb4b4b4}
T8b949e// Generate a DataPacket from a MeshPacket, or null if we didn't have enough data to do so
Tff7b72private Tff7b72fun Td2a8fftoDataPacketTb4b4b4(Te6edf3packetTb4b4b4: Te6edf3MeshPacketTb4b4b4)Tb4b4b4: Te6edf3DataPacket? Tff7b72= Tff7b72if Tb4b4b4(Tff7b72!Te6edf3packetTb4b4b4.Te6edf3hasDecodedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// We never convert packets that are not DataPackets
Tff7b72null
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72val Te6edf3data Tff7b72= Te6edf3packetTb4b4b4.Te6edf3decoded
Te6edf3DataPacketTb4b4b4(
Te6edf3from Tff7b72= Te6edf3toNodeIDTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3fromTb4b4b4)Tb4b4b4,
Te6edf3to Tff7b72= Te6edf3toNodeIDTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3toTb4b4b4)Tb4b4b4,
Te6edf3time Tff7b72= Te6edf3packetTb4b4b4.Te6edf3rxTime Tff7b72* T79c0ff1T79c0ff0T79c0ff0T79c0ff0LTb4b4b4,
Te6edf3id Tff7b72= Te6edf3packetTb4b4b4.Te6edf3idTb4b4b4,
Te6edf3dataType Tff7b72= Te6edf3dataTb4b4b4.Te6edf3portnumValueTb4b4b4,
Te6edf3bytes Tff7b72= Te6edf3dataTb4b4b4.Te6edf3payloadTb4b4b4.Te6edf3toByteArrayTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3hopLimit Tff7b72= Te6edf3packetTb4b4b4.Te6edf3hopLimitTb4b4b4,
Te6edf3channel Tff7b72= Tff7b72if Tb4b4b4(Te6edf3packetTb4b4b4.Te6edf3pkiEncryptedTb4b4b4) Te6edf3DataPacketTb4b4b4.Te6edf3PKC_CHANNEL_INDEX Tff7b72else Te6edf3packetTb4b4b4.Te6edf3channelTb4b4b4,
Te6edf3wantAck Tff7b72= Te6edf3packetTb4b4b4.Te6edf3wantAckTb4b4b4,
Te6edf3hopStart Tff7b72= Te6edf3packetTb4b4b4.Te6edf3hopStartTb4b4b4,
Te6edf3snr Tff7b72= Te6edf3packetTb4b4b4.Te6edf3rxSnrTb4b4b4,
Te6edf3rssi Tff7b72= Te6edf3packetTb4b4b4.Te6edf3rxRssiTb4b4b4,
Te6edf3replyId Tff7b72= Te6edf3dataTb4b4b4.Te6edf3replyIdTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8fftoMeshPacketTb4b4b4(Te6edf3pTb4b4b4: Te6edf3DataPacketTb4b4b4)Tb4b4b4: Te6edf3MeshPacket Tff7b72= Te6edf3newMeshPacketToTb4b4b4(Te6edf3pTb4b4b4.Te6edf3toTff7b72!!Tb4b4b4)Tb4b4b4.Te6edf3buildMeshPacketTb4b4b4(
Te6edf3id Tff7b72= Te6edf3pTb4b4b4.Te6edf3idTb4b4b4,
Te6edf3wantAck Tff7b72= Te6edf3pTb4b4b4.Te6edf3wantAckTb4b4b4,
Te6edf3hopLimit Tff7b72= Te6edf3pTb4b4b4.Te6edf3hopLimitTb4b4b4,
Te6edf3channel Tff7b72= Te6edf3pTb4b4b4.Te6edf3channelTb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3portnumValue Tff7b72= Te6edf3pTb4b4b4.Te6edf3dataType
Te6edf3payload Tff7b72= Te6edf3ByteStringTb4b4b4.Te6edf3copyFromTb4b4b4(Te6edf3pTb4b4b4.Te6edf3bytesTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3pTb4b4b4.Te6edf3replyId Tff7b72!Tff7b72= Tff7b72null Tff7b72&Tff7b72& Te6edf3pTb4b4b4.Te6edf3replyId Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72thisTb4b4b4.Te6edf3replyId Tff7b72= Te6edf3pTb4b4b4.Te6edf3replyIdTff7b72!!
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3rememberDataType Tff7b72=
Te6edf3setOfTb4b4b4(
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3TEXT_MESSAGE_APP_VALUETb4b4b4,
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3ALERT_APP_VALUETb4b4b4,
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3WAYPOINT_APP_VALUETb4b4b4,
Tb4b4b4)
Tff7b72private Tff7b72fun Td2a8ffrememberReactionTb4b4b4(Te6edf3packetTb4b4b4: Te6edf3MeshPacketTb4b4b4) Tff7b72= Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
Tff7b72val Te6edf3reaction Tff7b72=
Te6edf3ReactionEntityTb4b4b4(
Te6edf3replyId Tff7b72= Te6edf3packetTb4b4b4.Te6edf3decodedTb4b4b4.Te6edf3replyIdTb4b4b4,
Te6edf3userId Tff7b72= Te6edf3toNodeIDTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3fromTb4b4b4)Tb4b4b4,
Te6edf3emoji Tff7b72= Te6edf3packetTb4b4b4.Te6edf3decodedTb4b4b4.Te6edf3payloadTb4b4b4.Te6edf3toByteArrayTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3decodeToStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3timestamp Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3packetRepositoryTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3insertReactionTb4b4b4(Te6edf3reactionTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffrememberDataPacketTb4b4b4(Te6edf3dataPacketTb4b4b4: Te6edf3DataPacketTb4b4b4, Te6edf3updateNotificationTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72trueTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3dataPacketTb4b4b4.Te6edf3dataType Tff7b72!in Te6edf3rememberDataTypeTb4b4b4) Tff7b72return
Tff7b72val Te6edf3fromLocal Tff7b72= Te6edf3dataPacketTb4b4b4.Te6edf3from Tff7b72=Tff7b72= Te6edf3DataPacketTb4b4b4.Te6edf3ID_LOCAL
Tff7b72val Te6edf3toBroadcast Tff7b72= Te6edf3dataPacketTb4b4b4.Te6edf3to Tff7b72=Tff7b72= Te6edf3DataPacketTb4b4b4.Te6edf3ID_BROADCAST
Tff7b72val Te6edf3contactId Tff7b72= Tff7b72if Tb4b4b4(Te6edf3fromLocal Tff7b72|Tff7b72| Te6edf3toBroadcastTb4b4b4) Te6edf3dataPacketTb4b4b4.Te6edf3to Tff7b72else Te6edf3dataPacketTb4b4b4.Te6edf3from
T8b949e// contactKey: unique contact key filter (channel)+(nodeId)
Tff7b72val Te6edf3contactKey Tff7b72= Ta5d6ff"Tffd700${Te6edf3dataPacketTb4b4b4.Te6edf3channelTffd700}Tffd700$Te6edf3contactIdTa5d6ff"
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3PacketTb4b4b4(
Te6edf3uuid Tff7b72= T79c0ff0LTb4b4b4, T8b949e// autoGenerated
Te6edf3myNodeNum Tff7b72= Te6edf3myNodeNumTb4b4b4,
Te6edf3packetId Tff7b72= Te6edf3dataPacketTb4b4b4.Te6edf3idTb4b4b4,
Te6edf3port_num Tff7b72= Te6edf3dataPacketTb4b4b4.Te6edf3dataTypeTb4b4b4,
Te6edf3contact_key Tff7b72= Te6edf3contactKeyTb4b4b4,
Te6edf3received_time Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3read Tff7b72= Te6edf3fromLocalTb4b4b4,
Te6edf3data Tff7b72= Te6edf3dataPacketTb4b4b4,
Te6edf3snr Tff7b72= Te6edf3dataPacketTb4b4b4.Te6edf3snrTb4b4b4,
Te6edf3rssi Tff7b72= Te6edf3dataPacketTb4b4b4.Te6edf3rssiTb4b4b4,
Te6edf3hopsAway Tff7b72= Te6edf3dataPacketTb4b4b4.Te6edf3hopsAwayTb4b4b4,
Te6edf3replyId Tff7b72= Te6edf3dataPacketTb4b4b4.Te6edf3replyId Tff7b72?: T79c0ff0Tb4b4b4,
Tb4b4b4)
Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
Te6edf3packetRepositoryTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3insertTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Tff7b72val Te6edf3isMuted Tff7b72= Te6edf3getContactSettingsTb4b4b4(Te6edf3contactKeyTb4b4b4)Tb4b4b4.Te6edf3isMuted
Tff7b72if Tb4b4b4(Te6edf3packetToSaveTb4b4b4.Te6edf3port_num Tff7b72=Tff7b72= Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3ALERT_APP_VALUE Tff7b72&Tff7b72& Tff7b72!Te6edf3isMutedTb4b4b4) Tb4b4b4{
Te6edf3showAlertNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4, Te6edf3dataPacketTb4b4b4)
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3updateNotification Tff7b72&Tff7b72& Tff7b72!Te6edf3isMutedTb4b4b4) Tb4b4b4{
Te6edf3updateMessageNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4, Te6edf3dataPacketTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
T8b949e// Update our model and resend as needed for a MeshPacket we just received from the radio
Tff7b72private Tff7b72fun Td2a8ffhandleReceivedDataTb4b4b4(Te6edf3packetTb4b4b4: Te6edf3MeshPacketTb4b4b4) Tb4b4b4{
Te6edf3myNodeInfoTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3myInfo Tff7b72-Tff7b72>
Tff7b72val Te6edf3data Tff7b72= Te6edf3packetTb4b4b4.Te6edf3decoded
Tff7b72val Te6edf3bytes Tff7b72= Te6edf3dataTb4b4b4.Te6edf3payloadTb4b4b4.Te6edf3toByteArrayTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3fromId Tff7b72= Te6edf3toNodeIDTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3fromTb4b4b4)
Tff7b72val Te6edf3dataPacket Tff7b72= Te6edf3toDataPacketTb4b4b4(Te6edf3packetTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3dataPacket Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
T8b949e// We ignore most messages that we sent
Tff7b72val Te6edf3fromUs Tff7b72= Te6edf3myInfoTb4b4b4.Te6edf3myNodeNum Tff7b72=Tff7b72= Te6edf3packetTb4b4b4.Te6edf3from
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived data from Tffd700$Te6edf3fromIdTa5d6ff, portnum=Tffd700${Te6edf3dataTb4b4b4.Te6edf3portnumTffd700}Ta5d6ff Tffd700${Te6edf3bytesTb4b4b4.Te6edf3sizeTffd700}Ta5d6ff bytesTa5d6ff"Tb4b4b4)
Te6edf3dataPacketTb4b4b4.Te6edf3status Tff7b72= Te6edf3MessageStatusTb4b4b4.Te6edf3RECEIVED
T8b949e// if (p.hasUser()) handleReceivedUser(fromNum, p.user)
T8b949e// We tell other apps about most message types, but some may have sensitive data, so
T8b949e// that is not shared'
Tff7b72var Te6edf3shouldBroadcast Tff7b72= Tff7b72!Te6edf3fromUs
Tff7b72when Tb4b4b4(Te6edf3dataTb4b4b4.Te6edf3portnumValueTb4b4b4) Tb4b4b4{
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3TEXT_MESSAGE_APP_VALUE Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3dataTb4b4b4.Te6edf3replyId Tff7b72!Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3dataTb4b4b4.Te6edf3emoji Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived REPLY from Tffd700$Te6edf3fromIdTa5d6ff"Tb4b4b4)
Te6edf3rememberDataPacketTb4b4b4(Te6edf3dataPacketTb4b4b4)
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3dataTb4b4b4.Te6edf3replyId Tff7b72!Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3dataTb4b4b4.Te6edf3emoji Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived EMOJI from Tffd700$Te6edf3fromIdTa5d6ff"Tb4b4b4)
Te6edf3rememberReactionTb4b4b4(Te6edf3packetTb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived CLEAR_TEXT from Tffd700$Te6edf3fromIdTa5d6ff"Tb4b4b4)
Te6edf3rememberDataPacketTb4b4b4(Te6edf3dataPacketTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3ALERT_APP_VALUE Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived ALERT_APP from Tffd700$Te6edf3fromIdTa5d6ff"Tb4b4b4)
Te6edf3rememberDataPacketTb4b4b4(Te6edf3dataPacketTb4b4b4)
Tb4b4b4}
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3WAYPOINT_APP_VALUE Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72val Te6edf3u Tff7b72= Te6edf3MeshProtosTb4b4b4.Te6edf3WaypointTb4b4b4.Te6edf3parseFromTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3payloadTb4b4b4)
T8b949e// Validate locked Waypoints from the original sender
Tff7b72if Tb4b4b4(Te6edf3uTb4b4b4.Te6edf3lockedTo Tff7b72!Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3uTb4b4b4.Te6edf3lockedTo Tff7b72!Tff7b72= Te6edf3packetTb4b4b4.Te6edf3fromTb4b4b4) Tff7b72return
Te6edf3rememberDataPacketTb4b4b4(Te6edf3dataPacketTb4b4b4, Te6edf3uTb4b4b4.Te6edf3expire Tff7b72> Te6edf3currentSecondTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3POSITION_APP_VALUE Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72val Te6edf3u Tff7b72= Te6edf3MeshProtosTb4b4b4.Te6edf3PositionTb4b4b4.Te6edf3parseFromTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3payloadTb4b4b4)
T8b949e// debug("position_app ${packet.from} ${u.toOneLineString()}")
Tff7b72if Tb4b4b4(Te6edf3dataTb4b4b4.Te6edf3wantResponse Tff7b72&Tff7b72& Te6edf3uTb4b4b4.Te6edf3latitudeI Tff7b72=Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3uTb4b4b4.Te6edf3longitudeI Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffIgnoring nop position update from position requestTa5d6ff"Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3handleReceivedPositionTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3fromTb4b4b4, Te6edf3uTb4b4b4, Te6edf3dataPacketTb4b4b4.Te6edf3timeTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3NODEINFO_APP_VALUE Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fromUsTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3u Tff7b72=
Te6edf3MeshProtosTb4b4b4.Te6edf3UserTb4b4b4.Te6edf3parseFromTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3payloadTb4b4b4)Tb4b4b4.Te6edf3copy Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3isLicensedTb4b4b4) Te6edf3clearPublicKeyTb4b4b4(Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3packetTb4b4b4.Te6edf3viaMqttTb4b4b4) Te6edf3longName Tff7b72= Ta5d6ff"Tffd700$Te6edf3longNameTa5d6ff (MQTT)Ta5d6ff"
Tb4b4b4}
Te6edf3handleReceivedUserTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3fromTb4b4b4, Te6edf3uTb4b4b4, Te6edf3packetTb4b4b4.Te6edf3channelTb4b4b4)
Tb4b4b4}
T8b949e// Handle new telemetry info
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3TELEMETRY_APP_VALUE Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72val Te6edf3u Tff7b72=
Te6edf3TelemetryProtosTb4b4b4.Te6edf3TelemetryTb4b4b4.Te6edf3parseFromTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3payloadTb4b4b4)Tb4b4b4.Te6edf3copy Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3time Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Te6edf3time Tff7b72= Tb4b4b4(Te6edf3dataPacketTb4b4b4.Te6edf3time Tff7b72/ T79c0ff1T79c0ff0T79c0ff0T79c0ff0LTb4b4b4)Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)
Tb4b4b4}
Te6edf3handleReceivedTelemetryTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3fromTb4b4b4, Te6edf3uTb4b4b4)
Tb4b4b4}
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3ROUTING_APP_VALUE Tff7b72-Tff7b72> Tb4b4b4{
T8b949e// We always send ACKs to other apps, because they might care about the
T8b949e// messages they sent
Te6edf3shouldBroadcast Tff7b72= Tff7b72true
Tff7b72val Te6edf3u Tff7b72= Te6edf3MeshProtosTb4b4b4.Te6edf3RoutingTb4b4b4.Te6edf3parseFromTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3payloadTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3uTb4b4b4.Te6edf3errorReason Tff7b72=Tff7b72= Te6edf3MeshProtosTb4b4b4.Te6edf3RoutingTb4b4b4.Te6edf3ErrorTb4b4b4.Te6edf3DUTY_CYCLE_LIMITTb4b4b4) Tb4b4b4{
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3setErrorMessageTb4b4b4(Te6edf3getStringTb4b4b4(Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3error_duty_cycleTb4b4b4)Tb4b4b4)
Tb4b4b4}
Te6edf3handleAckNakTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3requestIdTb4b4b4, Te6edf3fromIdTb4b4b4, Te6edf3uTb4b4b4.Te6edf3errorReasonValueTb4b4b4)
Te6edf3packetHandlerTb4b4b4.Te6edf3removeResponseTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3requestIdTb4b4b4, Te6edf3complete Tff7b72= Tff7b72trueTb4b4b4)
Tb4b4b4}
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3ADMIN_APP_VALUE Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72val Te6edf3u Tff7b72= Te6edf3AdminProtosTb4b4b4.Te6edf3AdminMessageTb4b4b4.Te6edf3parseFromTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3payloadTb4b4b4)
Te6edf3handleReceivedAdminTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3fromTb4b4b4, Te6edf3uTb4b4b4)
Te6edf3shouldBroadcast Tff7b72= Tff7b72false
Tb4b4b4}
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3PAXCOUNTER_APP_VALUE Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72val Te6edf3p Tff7b72= Te6edf3PaxcountProtosTb4b4b4.Te6edf3PaxcountTb4b4b4.Te6edf3parseFromTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3payloadTb4b4b4)
Te6edf3handleReceivedPaxcounterTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3fromTb4b4b4, Te6edf3pTb4b4b4)
Te6edf3shouldBroadcast Tff7b72= Tff7b72false
Tb4b4b4}
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3STORE_FORWARD_APP_VALUE Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72val Te6edf3u Tff7b72= Te6edf3StoreAndForwardProtosTb4b4b4.Te6edf3StoreAndForwardTb4b4b4.Te6edf3parseFromTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3payloadTb4b4b4)
Te6edf3handleReceivedStoreAndForwardTb4b4b4(Te6edf3dataPacketTb4b4b4, Te6edf3uTb4b4b4)
Te6edf3shouldBroadcast Tff7b72= Tff7b72false
Tb4b4b4}
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3RANGE_TEST_APP_VALUE Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3moduleConfigTb4b4b4.Te6edf3rangeTestTb4b4b4.Te6edf3enabledTb4b4b4) Tff7b72return
Tff7b72val Te6edf3u Tff7b72= Te6edf3dataPacketTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3dataType Tff7b72= Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3TEXT_MESSAGE_APP_VALUETb4b4b4)
Te6edf3rememberDataPacketTb4b4b4(Te6edf3uTb4b4b4)
Tb4b4b4}
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3DETECTION_SENSOR_APP_VALUE Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72val Te6edf3u Tff7b72= Te6edf3dataPacketTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3dataType Tff7b72= Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3TEXT_MESSAGE_APP_VALUETb4b4b4)
Te6edf3rememberDataPacketTb4b4b4(Te6edf3uTb4b4b4)
Tb4b4b4}
Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3TRACEROUTE_APP_VALUE Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72val Te6edf3full Tff7b72= Te6edf3packetTb4b4b4.Te6edf3getFullTracerouteResponseTb4b4b4(Tff7b72::Te6edf3getUserNameTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3full Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3requestId Tff7b72= Te6edf3packetTb4b4b4.Te6edf3decodedTb4b4b4.Te6edf3requestId
Tff7b72val Te6edf3start Tff7b72= Te6edf3tracerouteStartTimesTb4b4b4.Te6edf3removeTb4b4b4(Te6edf3requestIdTb4b4b4)
Tff7b72val Te6edf3response Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3start Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3elapsedMs Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3start
Tff7b72val Te6edf3seconds Tff7b72= Te6edf3elapsedMs Tff7b72/ T79c0ff1T79c0ff0T79c0ff0T79c0ff0.0
Te6edf3infoTb4b4b4(Ta5d6ff"Ta5d6ffTraceroute Tffd700$Te6edf3requestIdTa5d6ff complete in Tffd700$Te6edf3secondsTa5d6ff sTa5d6ff"Tb4b4b4)
Ta5d6ff"Tffd700$Te6edf3fullTa5d6ff\Ta5d6ffnTa5d6ff\Ta5d6ffnDuration: Tffd700${Ta5d6ff"Tff7b72%Tb4b4b4.T79c0ff1fTa5d6ff"Tb4b4b4.Te6edf3formatTb4b4b4(Te6edf3secondsTb4b4b4)Tffd700}Ta5d6ff sTa5d6ff"
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3full
Tb4b4b4}
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3setTracerouteResponseTb4b4b4(Te6edf3responseTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72else Tff7b72-Tff7b72> Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffNo custom processing needed for Tffd700${Te6edf3dataTb4b4b4.Te6edf3portnumValueTffd700}Ta5d6ff"Tb4b4b4)
Tb4b4b4}
T8b949e// We always tell other apps when new data packets arrive
Tff7b72if Tb4b4b4(Te6edf3shouldBroadcastTb4b4b4) Tb4b4b4{
Te6edf3serviceBroadcastsTb4b4b4.Te6edf3broadcastReceivedDataTb4b4b4(Te6edf3dataPacketTb4b4b4)
Tb4b4b4}
Te6edf3GeeksvilleApplicationTb4b4b4.Te6edf3analyticsTb4b4b4.Te6edf3trackTb4b4b4(Ta5d6ff"Ta5d6ffnum_data_receiveTa5d6ff"Tb4b4b4, Te6edf3DataPairTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4)
Te6edf3GeeksvilleApplicationTb4b4b4.Te6edf3analyticsTb4b4b4.Te6edf3trackTb4b4b4(
Ta5d6ff"Ta5d6ffdata_receiveTa5d6ff"Tb4b4b4,
Te6edf3DataPairTb4b4b4(Ta5d6ff"Ta5d6ffnum_bytesTa5d6ff"Tb4b4b4, Te6edf3bytesTb4b4b4.Te6edf3sizeTb4b4b4)Tb4b4b4,
Te6edf3DataPairTb4b4b4(Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4, Te6edf3dataTb4b4b4.Te6edf3portnumValueTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhandleReceivedAdminTb4b4b4(Te6edf3fromNodeNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3aTb4b4b4: Te6edf3AdminProtosTb4b4b4.Te6edf3AdminMessageTb4b4b4) Tb4b4b4{
Tff7b72when Tb4b4b4(Te6edf3aTb4b4b4.Te6edf3payloadVariantCaseTb4b4b4) Tb4b4b4{
Te6edf3AdminProtosTb4b4b4.Te6edf3AdminMessageTb4b4b4.Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3GET_CONFIG_RESPONSE Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3fromNodeNum Tff7b72=Tff7b72= Te6edf3myNodeNumTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3response Tff7b72= Te6edf3aTb4b4b4.Te6edf3getConfigResponse
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffAdmin: received config Tffd700${Te6edf3responseTb4b4b4.Te6edf3payloadVariantCaseTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3setLocalConfigTb4b4b4(Te6edf3responseTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Te6edf3AdminProtosTb4b4b4.Te6edf3AdminMessageTb4b4b4.Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3GET_CHANNEL_RESPONSE Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3fromNodeNum Tff7b72=Tff7b72= Te6edf3myNodeNumTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3mi Tff7b72= Te6edf3myNodeInfo
Tff7b72if Tb4b4b4(Te6edf3mi Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3ch Tff7b72= Te6edf3aTb4b4b4.Te6edf3getChannelResponse
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffAdmin: Received channel Tffd700${Te6edf3chTb4b4b4.Te6edf3indexTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3chTb4b4b4.Te6edf3index Tff7b72+ T79c0ff1 Tff7b72< Te6edf3miTb4b4b4.Te6edf3maxChannelsTb4b4b4) Tb4b4b4{
Te6edf3handleChannelTb4b4b4(Te6edf3chTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Te6edf3AdminProtosTb4b4b4.Te6edf3AdminMessageTb4b4b4.Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3GET_DEVICE_METADATA_RESPONSE Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffAdmin: received DeviceMetadata from Tffd700$Te6edf3fromNodeNumTa5d6ff"Tb4b4b4)
Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3insertMetadataTb4b4b4(Te6edf3fromNodeNumTb4b4b4, Te6edf3aTb4b4b4.Te6edf3getDeviceMetadataResponseTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72else Tff7b72-Tff7b72> Te6edf3warnTb4b4b4(Ta5d6ff"Ta5d6ffNo special processing needed for Tffd700${Te6edf3aTb4b4b4.Te6edf3payloadVariantCaseTffd700}Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffAdmin: Received session_passkey from Tffd700$Te6edf3fromNodeNumTa5d6ff"Tb4b4b4)
Te6edf3sessionPasskey Tff7b72= Te6edf3aTb4b4b4.Te6edf3sessionPasskey
Tb4b4b4}
T8b949e// Update our DB of users based on someone sending out a User subpacket
Tff7b72private Tff7b72fun Td2a8ffhandleReceivedUserTb4b4b4(Te6edf3fromNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3pTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3UserTb4b4b4, Te6edf3channelTb4b4b4: Tffa657Int Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3updateNodeInfoTb4b4b4(Te6edf3fromNumTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3newNode Tff7b72= Tb4b4b4(Tffa657itTb4b4b4.Te6edf3isUnknownUser Tff7b72&Tff7b72& Te6edf3pTb4b4b4.Te6edf3hwModel Tff7b72!Tff7b72= Te6edf3MeshProtosTb4b4b4.Te6edf3HardwareModelTb4b4b4.Te6edf3UNSETTb4b4b4)
Tff7b72val Te6edf3keyMatch Tff7b72= Tff7b72!Tffa657itTb4b4b4.Te6edf3hasPKC Tff7b72|Tff7b72| Tffa657itTb4b4b4.Te6edf3userTb4b4b4.Te6edf3publicKey Tff7b72=Tff7b72= Te6edf3pTb4b4b4.Te6edf3publicKey
Tffa657itTb4b4b4.Te6edf3user Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3keyMatchTb4b4b4) Tb4b4b4{
Te6edf3p
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3copy Tb4b4b4{
Te6edf3warnTb4b4b4(Ta5d6ff"Ta5d6ffPublic key mismatch from Tffd700$Te6edf3longNameTa5d6ff (Tffd700$Te6edf3shortNameTa5d6ff)Ta5d6ff"Tb4b4b4)
Te6edf3publicKey Tff7b72= Te6edf3NodeEntityTb4b4b4.Te6edf3ERROR_BYTE_STRING
Tb4b4b4}
Tb4b4b4}
Tffa657itTb4b4b4.Te6edf3longName Tff7b72= Te6edf3pTb4b4b4.Te6edf3longName
Tffa657itTb4b4b4.Te6edf3shortName Tff7b72= Te6edf3pTb4b4b4.Te6edf3shortName
Tffa657itTb4b4b4.Te6edf3channel Tff7b72= Te6edf3channel
Tff7b72if Tb4b4b4(Te6edf3newNodeTb4b4b4) Tb4b4b4{
Te6edf3serviceNotificationsTb4b4b4.Te6edf3showNewNodeSeenNotificationTb4b4b4(Tffa657itTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
T8b949e/**
* Update our DB of users based on someone sending out a Position subpacket
*
* @param defaultTime in msecs since 1970
*/
Tff7b72private Tff7b72fun Td2a8ffhandleReceivedPositionTb4b4b4(
Te6edf3fromNumTb4b4b4: Tffa657IntTb4b4b4,
Te6edf3pTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3PositionTb4b4b4,
Te6edf3defaultTimeTb4b4b4: Tffa657Long Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4) Tb4b4b4{
T8b949e// Nodes periodically send out position updates, but those updates might not contain a lat &
T8b949e// lon (because no GPS
T8b949e// lock)
T8b949e// We like to look at the local node to see if it has been sending out valid lat/lon, so for
T8b949e// the LOCAL node
T8b949e// (only)
T8b949e// we don't record these nop position updates
Tff7b72if Tb4b4b4(Te6edf3myNodeNum Tff7b72=Tff7b72= Te6edf3fromNum Tff7b72&Tff7b72& Te6edf3pTb4b4b4.Te6edf3latitudeI Tff7b72=Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3pTb4b4b4.Te6edf3longitudeI Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffIgnoring nop position update for the local nodeTa5d6ff"Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3updateNodeInfoTb4b4b4(Te6edf3fromNumTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffupdate position: Tffd700${Tffa657itTb4b4b4.Te6edf3longNameTff7b72?.Te6edf3toPIIStringTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff with Tffd700${Te6edf3pTb4b4b4.Te6edf3toPIIStringTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tffa657itTb4b4b4.Te6edf3setPositionTb4b4b4(Te6edf3pTb4b4b4, Tb4b4b4(Te6edf3defaultTime Tff7b72/ T79c0ff1T79c0ff0T79c0ff0T79c0ff0LTb4b4b4)Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
T8b949e// Update our DB of users based on someone sending out a Telemetry subpacket
Tff7b72private Tff7b72fun Td2a8ffhandleReceivedTelemetryTb4b4b4(Te6edf3fromNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3tTb4b4b4: Te6edf3TelemetryProtosTb4b4b4.Te6edf3TelemetryTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3isRemote Tff7b72= Tb4b4b4(Te6edf3fromNum Tff7b72!Tff7b72= Te6edf3myNodeNumTb4b4b4)
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3isRemote Tff7b72&Tff7b72& Te6edf3tTb4b4b4.Te6edf3hasLocalStatsTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3localStatsTelemetry Tff7b72= Te6edf3t
Te6edf3maybeUpdateServiceStatusNotificationTb4b4b4(Tb4b4b4)
Tb4b4b4}
Te6edf3updateNodeInfoTb4b4b4(Te6edf3fromNumTb4b4b4) Tb4b4b4{
Tff7b72when Tb4b4b4{
Te6edf3tTb4b4b4.Te6edf3hasDeviceMetricsTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tb4b4b4{
Tffa657itTb4b4b4.Te6edf3deviceTelemetry Tff7b72= Te6edf3t
Tff7b72if Tb4b4b4(Te6edf3fromNum Tff7b72=Tff7b72= Te6edf3myNodeNum Tff7b72|Tff7b72| Tb4b4b4(Te6edf3isRemote Tff7b72&Tff7b72& Tffa657itTb4b4b4.Te6edf3isFavoriteTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(
Te6edf3tTb4b4b4.Te6edf3deviceMetricsTb4b4b4.Te6edf3voltage Tff7b72> Te6edf3batteryPercentUnsupported Tff7b72&Tff7b72&
Te6edf3tTb4b4b4.Te6edf3deviceMetricsTb4b4b4.Te6edf3batteryLevel Tff7b72<Tff7b72= Te6edf3batteryPercentLowThreshold
Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3shouldBatteryNotificationShowTb4b4b4(Te6edf3fromNumTb4b4b4, Te6edf3tTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3serviceNotificationsTb4b4b4.Te6edf3showOrUpdateLowBatteryNotificationTb4b4b4(Tffa657itTb4b4b4, Te6edf3isRemoteTb4b4b4)
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3batteryPercentCooldownsTb4b4b4.Te6edf3containsKeyTb4b4b4(Te6edf3fromNumTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3batteryPercentCooldownsTb4b4b4.Te6edf3removeTb4b4b4(Te6edf3fromNumTb4b4b4)
Tb4b4b4}
Te6edf3serviceNotificationsTb4b4b4.Te6edf3cancelLowBatteryNotificationTb4b4b4(Tffa657itTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Te6edf3tTb4b4b4.Te6edf3hasEnvironmentMetricsTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657itTb4b4b4.Te6edf3environmentTelemetry Tff7b72= Te6edf3t
Te6edf3tTb4b4b4.Te6edf3hasPowerMetricsTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657itTb4b4b4.Te6edf3powerTelemetry Tff7b72= Te6edf3t
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffshouldBatteryNotificationShowTb4b4b4(Te6edf3fromNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3tTb4b4b4: Te6edf3TelemetryProtosTb4b4b4.Te6edf3TelemetryTb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72val Te6edf3isRemote Tff7b72= Tb4b4b4(Te6edf3fromNum Tff7b72!Tff7b72= Te6edf3myNodeNumTb4b4b4)
Tff7b72var Te6edf3shouldDisplay Tff7b72= Tff7b72false
Tff7b72var Te6edf3forceDisplay Tff7b72= Tff7b72false
Tff7b72when Tb4b4b4{
Te6edf3tTb4b4b4.Te6edf3deviceMetricsTb4b4b4.Te6edf3batteryLevel Tff7b72<Tff7b72= Te6edf3batteryPercentCriticalThreshold Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3shouldDisplay Tff7b72= Tff7b72true
Te6edf3forceDisplay Tff7b72= Tff7b72true
Tb4b4b4}
Te6edf3tTb4b4b4.Te6edf3deviceMetricsTb4b4b4.Te6edf3batteryLevel Tff7b72=Tff7b72= Te6edf3batteryPercentLowThreshold Tff7b72-Tff7b72> Te6edf3shouldDisplay Tff7b72= Tff7b72true
Te6edf3tTb4b4b4.Te6edf3deviceMetricsTb4b4b4.Te6edf3batteryLevelTb4b4b4.Te6edf3modTb4b4b4(Te6edf3batteryPercentLowDivisorTb4b4b4) Tff7b72=Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Tff7b72!Te6edf3isRemote Tff7b72-Tff7b72> Te6edf3shouldDisplay Tff7b72= Tff7b72true
Te6edf3isRemote Tff7b72-Tff7b72> Te6edf3shouldDisplay Tff7b72= Tff7b72true
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3shouldDisplayTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3now Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4) Tff7b72/ T79c0ff1T79c0ff0T79c0ff0T79c0ff0
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3batteryPercentCooldownsTb4b4b4.Te6edf3containsKeyTb4b4b4(Te6edf3fromNumTb4b4b4)Tb4b4b4) Te6edf3batteryPercentCooldownsTff7b72[Te6edf3fromNumTff7b72] Tff7b72= T79c0ff0
Tff7b72if Tb4b4b4(Tb4b4b4(Te6edf3now Tff7b72- Te6edf3batteryPercentCooldownsTff7b72[Te6edf3fromNumTff7b72]Tff7b72!!Tb4b4b4) Tff7b72>Tff7b72= Te6edf3batteryPercentCooldownSeconds Tff7b72|Tff7b72| Te6edf3forceDisplayTb4b4b4) Tb4b4b4{
Te6edf3batteryPercentCooldownsTff7b72[Te6edf3fromNumTff7b72] Tff7b72= Te6edf3now
Tff7b72return Tff7b72true
Tb4b4b4}
Tb4b4b4}
Tff7b72return Tff7b72false
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhandleReceivedPaxcounterTb4b4b4(Te6edf3fromNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3pTb4b4b4: Te6edf3PaxcountProtosTb4b4b4.Te6edf3PaxcountTb4b4b4) Tb4b4b4{
Te6edf3updateNodeInfoTb4b4b4(Te6edf3fromNumTb4b4b4) Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3paxcounter Tff7b72= Te6edf3p Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhandleReceivedStoreAndForwardTb4b4b4(Te6edf3dataPacketTb4b4b4: Te6edf3DataPacketTb4b4b4, Te6edf3sTb4b4b4: Te6edf3StoreAndForwardProtosTb4b4b4.Te6edf3StoreAndForwardTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffStoreAndForward: Tffd700${Te6edf3sTb4b4b4.Te6edf3variantCaseTffd700}Ta5d6ff Tffd700${Te6edf3sTb4b4b4.Te6edf3rrTffd700}Ta5d6ff from Tffd700${Te6edf3dataPacketTb4b4b4.Te6edf3fromTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72when Tb4b4b4(Te6edf3sTb4b4b4.Te6edf3variantCaseTb4b4b4) Tb4b4b4{
Te6edf3StoreAndForwardProtosTb4b4b4.Te6edf3StoreAndForwardTb4b4b4.Te6edf3VariantCaseTb4b4b4.Te6edf3STATS Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72val Te6edf3u Tff7b72=
Te6edf3dataPacketTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3bytes Tff7b72= Te6edf3sTb4b4b4.Te6edf3statsTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3encodeToByteArrayTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3dataType Tff7b72= Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3TEXT_MESSAGE_APP_VALUETb4b4b4,
Tb4b4b4)
Te6edf3rememberDataPacketTb4b4b4(Te6edf3uTb4b4b4)
Tb4b4b4}
Te6edf3StoreAndForwardProtosTb4b4b4.Te6edf3StoreAndForwardTb4b4b4.Te6edf3VariantCaseTb4b4b4.Te6edf3HISTORY Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72val Te6edf3text Tff7b72=
Ta5d6ff"""
Ta5d6ff Total messages: Tffd700${Te6edf3sTb4b4b4.Te6edf3historyTb4b4b4.Te6edf3historyMessagesTffd700}
Ta5d6ff History window: Tffd700${Te6edf3sTb4b4b4.Te6edf3historyTb4b4b4.Te6edf3window Tff7b72/ T79c0ff6T79c0ff0T79c0ff0T79c0ff0T79c0ff0Tffd700}Ta5d6ff min
Last request: Tffd700${Te6edf3sTb4b4b4.Te6edf3historyTb4b4b4.Te6edf3lastRequestTffd700}
Ta5d6ff Ta5d6ff"""
Tb4b4b4.Te6edf3trimIndentTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3u Tff7b72=
Te6edf3dataPacketTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3bytes Tff7b72= Te6edf3textTb4b4b4.Te6edf3encodeToByteArrayTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3dataType Tff7b72= Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3TEXT_MESSAGE_APP_VALUETb4b4b4,
Tb4b4b4)
Te6edf3rememberDataPacketTb4b4b4(Te6edf3uTb4b4b4)
Tb4b4b4}
Te6edf3StoreAndForwardProtosTb4b4b4.Te6edf3StoreAndForwardTb4b4b4.Te6edf3VariantCaseTb4b4b4.Te6edf3TEXT Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3sTb4b4b4.Te6edf3rr Tff7b72=Tff7b72= Te6edf3StoreAndForwardProtosTb4b4b4.Te6edf3StoreAndForwardTb4b4b4.Te6edf3RequestResponseTb4b4b4.Te6edf3ROUTER_TEXT_BROADCASTTb4b4b4) Tb4b4b4{
Te6edf3dataPacketTb4b4b4.Te6edf3to Tff7b72= Te6edf3DataPacketTb4b4b4.Te6edf3ID_BROADCAST
Tb4b4b4}
Tff7b72val Te6edf3u Tff7b72=
Te6edf3dataPacketTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3bytes Tff7b72= Te6edf3sTb4b4b4.Te6edf3textTb4b4b4.Te6edf3toByteArrayTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3dataType Tff7b72= Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3TEXT_MESSAGE_APP_VALUETb4b4b4)
Te6edf3rememberDataPacketTb4b4b4(Te6edf3uTb4b4b4)
Tb4b4b4}
Tff7b72else Tff7b72-Tff7b72> Tb4b4b4{Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
T8b949e// If apps try to send packets when our radio is sleeping, we queue them here instead
Tff7b72private Tff7b72val Te6edf3offlineSentPackets Tff7b72= Te6edf3mutableListOfTff7b72<Te6edf3DataPacketTff7b72>Tb4b4b4(Tb4b4b4)
T8b949e// Update our model and resend as needed for a MeshPacket we just received from the radio
Tff7b72private Tff7b72fun Td2a8ffhandleReceivedMeshPacketTb4b4b4(Te6edf3packetTb4b4b4: Te6edf3MeshPacketTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3haveNodeDBTb4b4b4) Tb4b4b4{
Te6edf3processReceivedMeshPacketTb4b4b4(
Te6edf3packet
Tb4b4b4.Te6edf3toBuilderTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3apply Tb4b4b4{
T8b949e// If the rxTime was not set by the device, update with current time
Tff7b72if Tb4b4b4(Te6edf3packetTb4b4b4.Te6edf3rxTime Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Te6edf3setRxTimeTb4b4b4(Te6edf3currentSecondTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3onNodeDBChangedTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3warnTb4b4b4(Ta5d6ff"Ta5d6ffIgnoring early received packet: Tffd700${Te6edf3packetTb4b4b4.Te6edf3toOneLineStringTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
T8b949e// earlyReceivedPackets.add(packet)
T8b949e// logAssert(earlyReceivedPackets.size < 128) // The max should normally be about 32,
T8b949e// but if the device is
T8b949e// messed up it might try to send forever
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffsendNowTb4b4b4(Te6edf3pTb4b4b4: Te6edf3DataPacketTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3packet Tff7b72= Te6edf3toMeshPacketTb4b4b4(Te6edf3pTb4b4b4)
Te6edf3pTb4b4b4.Te6edf3time Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4) T8b949e// update time to the actual time we started sending
T8b949e// debug("Sending to radio: ${packet.toPIIString()}")
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(Te6edf3packetTb4b4b4) Tb4b4b4{ Te6edf3connectionState Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffprocessQueuedPacketsTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3sentPackets Tff7b72= Te6edf3mutableListOfTff7b72<Te6edf3DataPacketTff7b72>Tb4b4b4(Tb4b4b4)
Te6edf3offlineSentPacketsTb4b4b4.Te6edf3forEach Tb4b4b4{ Te6edf3p Tff7b72-Tff7b72>
Tff7b72try Tb4b4b4{
Te6edf3sendNowTb4b4b4(Te6edf3pTb4b4b4)
Te6edf3sentPacketsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3pTb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Te6edf3errormsgTb4b4b4(Ta5d6ff"Ta5d6ffError sending queued message:Ta5d6ff"Tb4b4b4, Te6edf3exTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Te6edf3offlineSentPacketsTb4b4b4.Te6edf3removeAllTb4b4b4(Te6edf3sentPacketsTb4b4b4)
Tb4b4b4}
T8b949e/** Handle an ack/nak packet by updating sent message status */
Tff7b72private Tff7b72fun Td2a8ffhandleAckNakTb4b4b4(Te6edf3requestIdTb4b4b4: Tffa657IntTb4b4b4, Te6edf3fromIdTb4b4b4: Tffa657StringTb4b4b4, Te6edf3routingErrorTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4{
Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
Tff7b72val Te6edf3isAck Tff7b72= Te6edf3routingError Tff7b72=Tff7b72= Te6edf3MeshProtosTb4b4b4.Te6edf3RoutingTb4b4b4.Te6edf3ErrorTb4b4b4.Te6edf3NONE_VALUE
Tff7b72val Te6edf3p Tff7b72= Te6edf3packetRepositoryTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3getPacketByIdTb4b4b4(Te6edf3requestIdTb4b4b4)
T8b949e// distinguish real ACKs coming from the intended receiver
Tff7b72val Te6edf3m Tff7b72=
Tff7b72when Tb4b4b4{
Te6edf3isAck Tff7b72&Tff7b72& Te6edf3fromId Tff7b72=Tff7b72= Te6edf3pTff7b72?.Te6edf3dataTff7b72?.Te6edf3to Tff7b72-Tff7b72> Te6edf3MessageStatusTb4b4b4.Te6edf3RECEIVED
Te6edf3isAck Tff7b72-Tff7b72> Te6edf3MessageStatusTb4b4b4.Te6edf3DELIVERED
Tff7b72else Tff7b72-Tff7b72> Te6edf3MessageStatusTb4b4b4.Te6edf3ERROR
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3p Tff7b72!Tff7b72= Tff7b72null Tff7b72&Tff7b72& Te6edf3pTb4b4b4.Te6edf3dataTb4b4b4.Te6edf3status Tff7b72!Tff7b72= Te6edf3MessageStatusTb4b4b4.Te6edf3RECEIVEDTb4b4b4) Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3dataTb4b4b4.Te6edf3status Tff7b72= Te6edf3m
Te6edf3pTb4b4b4.Te6edf3routingError Tff7b72= Te6edf3routingError
Te6edf3packetRepositoryTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3updateTb4b4b4(Te6edf3pTb4b4b4)
Tb4b4b4}
Te6edf3serviceBroadcastsTb4b4b4.Te6edf3broadcastMessageStatusTb4b4b4(Te6edf3requestIdTb4b4b4, Te6edf3mTb4b4b4)
Tb4b4b4}
Tb4b4b4}
T8b949e// Update our model and resend as needed for a MeshPacket we just received from the radio
Tff7b72private Tff7b72fun Td2a8ffprocessReceivedMeshPacketTb4b4b4(Te6edf3packetTb4b4b4: Te6edf3MeshPacketTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3fromNum Tff7b72= Te6edf3packetTb4b4b4.Te6edf3from
T8b949e// FIXME, perhaps we could learn our node ID by looking at any to packets the radio
T8b949e// decided to pass through to us (except for broadcast packets)
T8b949e// val toNum = packet.to
T8b949e// debug("Received: $packet")
Tff7b72if Tb4b4b4(Te6edf3packetTb4b4b4.Te6edf3hasDecodedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3UUIDTb4b4b4.Te6edf3randomUUIDTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffPacketTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3raw_message Tff7b72= Te6edf3packetTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fromNum Tff7b72= Te6edf3packetTb4b4b4.Te6edf3fromTb4b4b4,
Te6edf3portNum Tff7b72= Te6edf3packetTb4b4b4.Te6edf3decodedTb4b4b4.Te6edf3portnumValueTb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3fromRadio Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3packet Tff7b72= Te6edf3packet Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3insertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{ Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3emitMeshPacketTb4b4b4(Te6edf3packetTb4b4b4) Tb4b4b4}
T8b949e// Update last seen for the node that sent the packet, but also for _our node_ because
T8b949e// anytime a packet
T8b949e// passes
T8b949e// through our node on the way to the phone that means that local node is also alive in
T8b949e// the mesh
Tff7b72val Te6edf3isOtherNode Tff7b72= Te6edf3myNodeNum Tff7b72!Tff7b72= Te6edf3fromNum
Te6edf3updateNodeInfoTb4b4b4(Te6edf3myNodeNumTb4b4b4, Te6edf3withBroadcast Tff7b72= Te6edf3isOtherNodeTb4b4b4) Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3lastHeard Tff7b72= Te6edf3currentSecondTb4b4b4(Tb4b4b4) Tb4b4b4}
T8b949e// Do not generate redundant broadcasts of node change for this bookkeeping
T8b949e// updateNodeInfo call
T8b949e// because apps really only care about important updates of node state - which
T8b949e// handledReceivedData will give
T8b949e// them
Te6edf3updateNodeInfoTb4b4b4(Te6edf3fromNumTb4b4b4, Te6edf3withBroadcast Tff7b72= Tff7b72falseTb4b4b4, Te6edf3channel Tff7b72= Te6edf3packetTb4b4b4.Te6edf3channelTb4b4b4) Tb4b4b4{
T8b949e// Update our last seen based on any valid timestamps. If the device didn't provide
T8b949e// a timestamp make
T8b949e// one
Tffa657itTb4b4b4.Te6edf3lastHeard Tff7b72= Te6edf3packetTb4b4b4.Te6edf3rxTime
Tffa657itTb4b4b4.Te6edf3snr Tff7b72= Te6edf3packetTb4b4b4.Te6edf3rxSnr
Tffa657itTb4b4b4.Te6edf3rssi Tff7b72= Te6edf3packetTb4b4b4.Te6edf3rxRssi
T8b949e// Generate our own hopsAway, comparing hopStart to hopLimit.
Tffa657itTb4b4b4.Te6edf3hopsAway Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3packetTb4b4b4.Te6edf3decodedTb4b4b4.Te6edf3portnumValue Tff7b72=Tff7b72= Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3RANGE_TEST_APP_VALUETb4b4b4) Tb4b4b4{
T79c0ff0 T8b949e// These don't come with the .hop params, but do not propogate, so they must be 0
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3packetTb4b4b4.Te6edf3hopStart Tff7b72=Tff7b72= T79c0ff0 Tff7b72|Tff7b72| Te6edf3packetTb4b4b4.Te6edf3hopLimit Tff7b72> Te6edf3packetTb4b4b4.Te6edf3hopStartTb4b4b4) Tb4b4b4{
Tff7b72-T79c0ff1
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3packetTb4b4b4.Te6edf3hopStart Tff7b72- Te6edf3packetTb4b4b4.Te6edf3hopLimit
Tb4b4b4}
Tb4b4b4}
Te6edf3handleReceivedDataTb4b4b4(Te6edf3packetTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffinsertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4: Te6edf3MeshLogTb4b4b4) Tb4b4b4{
Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
T8b949e// Do not log, because might contain PII
T8b949e// info("insert: ${packetToSave.message_type} =
T8b949e// ${packetToSave.raw_message.toOneLineString()}")
Te6edf3meshLogRepositoryTb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3insertTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffsetLocalConfigTb4b4b4(Te6edf3configTb4b4b4: Te6edf3ConfigProtosTb4b4b4.Te6edf3ConfigTb4b4b4) Tb4b4b4{
Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{ Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3setLocalConfigTb4b4b4(Te6edf3configTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffsetLocalModuleConfigTb4b4b4(Te6edf3configTb4b4b4: Te6edf3ModuleConfigProtosTb4b4b4.Te6edf3ModuleConfigTb4b4b4) Tb4b4b4{
Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{ Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3setLocalModuleConfigTb4b4b4(Te6edf3configTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffupdateChannelSettingsTb4b4b4(Te6edf3chTb4b4b4: Te6edf3ChannelProtosTb4b4b4.Te6edf3ChannelTb4b4b4) Tff7b72=
Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{ Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3updateChannelSettingsTb4b4b4(Te6edf3chTb4b4b4) Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcurrentSecondTb4b4b4(Tb4b4b4) Tff7b72= Tb4b4b4(Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4) Tff7b72/ T79c0ff1T79c0ff0T79c0ff0T79c0ff0Tb4b4b4)Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)
T8b949e// If we just changed our nodedb, we might want to do somethings
Tff7b72private Tff7b72fun Td2a8ffonNodeDBChangedTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3maybeUpdateServiceStatusNotificationTb4b4b4(Tb4b4b4)
Tb4b4b4}
T8b949e/** Send in analytics about mesh connection */
Tff7b72private Tff7b72fun Td2a8ffreportConnectionTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3radioModel Tff7b72= Te6edf3DataPairTb4b4b4(Ta5d6ff"Ta5d6ffradio_modelTa5d6ff"Tb4b4b4, Te6edf3myNodeInfoTff7b72?.Te6edf3model Tff7b72?: Ta5d6ff"Ta5d6ffunknownTa5d6ff"Tb4b4b4)
Te6edf3GeeksvilleApplicationTb4b4b4.Te6edf3analyticsTb4b4b4.Te6edf3trackTb4b4b4(
Ta5d6ff"Ta5d6ffmesh_connectTa5d6ff"Tb4b4b4,
Te6edf3DataPairTb4b4b4(Ta5d6ff"Ta5d6ffnum_nodesTa5d6ff"Tb4b4b4, Te6edf3numNodesTb4b4b4)Tb4b4b4,
Te6edf3DataPairTb4b4b4(Ta5d6ff"Ta5d6ffnum_onlineTa5d6ff"Tb4b4b4, Te6edf3numOnlineNodesTb4b4b4)Tb4b4b4,
Te6edf3radioModelTb4b4b4,
Tb4b4b4)
T8b949e// Once someone connects to hardware start tracking the approximate number of nodes in their
T8b949e// mesh
T8b949e// this allows us to collect stats on what typical mesh size is and to tell difference
T8b949e// between users who just
T8b949e// downloaded the app, vs has connected it to some hardware.
Te6edf3GeeksvilleApplicationTb4b4b4.Te6edf3analyticsTb4b4b4.Te6edf3setUserInfoTb4b4b4(Te6edf3DataPairTb4b4b4(Ta5d6ff"Ta5d6ffnum_nodesTa5d6ff"Tb4b4b4, Te6edf3numNodesTb4b4b4)Tb4b4b4, Te6edf3radioModelTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72var Te6edf3sleepTimeoutTb4b4b4: Te6edf3Job? Tff7b72= Tff7b72null
T8b949e// msecs since 1970 we started this connection
Tff7b72private Tff7b72var Te6edf3connectTimeMsec Tff7b72= T79c0ff0L
T8b949e// Called when we gain/lose connection to our radio
Tff7b72private Tff7b72fun Td2a8ffonConnectionChangedTb4b4b4(Te6edf3cTb4b4b4: Te6edf3ConnectionStateTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffonConnectionChanged: Tffd700$Te6edf3connectionStateTa5d6ff -> Tffd700$Te6edf3cTa5d6ff"Tb4b4b4)
T8b949e// Perform all the steps needed once we start waiting for device sleep to complete
Tff7b72fun Td2a8ffstartDeviceSleepTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3stopPacketQueueTb4b4b4(Tb4b4b4)
Te6edf3stopLocationRequestsTb4b4b4(Tb4b4b4)
Te6edf3stopMqttClientProxyTb4b4b4(Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3connectTimeMsec Tff7b72!Tff7b72= T79c0ff0LTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3now Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)
Te6edf3connectTimeMsec Tff7b72= T79c0ff0L
Te6edf3GeeksvilleApplicationTb4b4b4.Te6edf3analyticsTb4b4b4.Te6edf3trackTb4b4b4(Ta5d6ff"Ta5d6ffconnected_secondsTa5d6ff"Tb4b4b4, Te6edf3DataPairTb4b4b4(Tb4b4b4(Te6edf3now Tff7b72- Te6edf3connectTimeMsecTb4b4b4) Tff7b72/ T79c0ff1T79c0ff0T79c0ff0T79c0ff0.0Tb4b4b4)Tb4b4b4)
Tb4b4b4}
T8b949e// Have our timeout fire in the appropriate number of seconds
Te6edf3sleepTimeout Tff7b72=
Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
Tff7b72try Tb4b4b4{
T8b949e// If we have a valid timeout, wait that long (+30 seconds) otherwise, just
T8b949e// wait 30 seconds
Tff7b72val Te6edf3timeout Tff7b72= Tb4b4b4(Te6edf3localConfigTb4b4b4.Te6edf3powerTff7b72?.Te6edf3lsSecs Tff7b72?: T79c0ff0Tb4b4b4) Tff7b72+ T79c0ff3T79c0ff0
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffWaiting for sleeping device, timeout=Tffd700$Te6edf3timeoutTa5d6ff secsTa5d6ff"Tb4b4b4)
Te6edf3delayTb4b4b4(Te6edf3timeout Tff7b72* T79c0ff1T79c0ff0T79c0ff0T79c0ff0LTb4b4b4)
Te6edf3warnTb4b4b4(Ta5d6ff"Ta5d6ffDevice timeout out, setting disconnectedTa5d6ff"Tb4b4b4)
Te6edf3onConnectionChangedTb4b4b4(Te6edf3ConnectionStateTb4b4b4.Te6edf3DISCONNECTEDTb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3CancellationExceptionTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffdevice sleep timeout cancelledTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
T8b949e// broadcast an intent with our new connection state
Te6edf3serviceBroadcastsTb4b4b4.Te6edf3broadcastConnectionTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffstartDisconnectTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3stopPacketQueueTb4b4b4(Tb4b4b4)
Te6edf3stopLocationRequestsTb4b4b4(Tb4b4b4)
Te6edf3stopMqttClientProxyTb4b4b4(Tb4b4b4)
Te6edf3GeeksvilleApplicationTb4b4b4.Te6edf3analyticsTb4b4b4.Te6edf3trackTb4b4b4(
Ta5d6ff"Ta5d6ffmesh_disconnectTa5d6ff"Tb4b4b4,
Te6edf3DataPairTb4b4b4(Ta5d6ff"Ta5d6ffnum_nodesTa5d6ff"Tb4b4b4, Te6edf3numNodesTb4b4b4)Tb4b4b4,
Te6edf3DataPairTb4b4b4(Ta5d6ff"Ta5d6ffnum_onlineTa5d6ff"Tb4b4b4, Te6edf3numOnlineNodesTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3GeeksvilleApplicationTb4b4b4.Te6edf3analyticsTb4b4b4.Te6edf3trackTb4b4b4(Ta5d6ff"Ta5d6ffnum_nodesTa5d6ff"Tb4b4b4, Te6edf3DataPairTb4b4b4(Te6edf3numNodesTb4b4b4)Tb4b4b4)
T8b949e// broadcast an intent with our new connection state
Te6edf3serviceBroadcastsTb4b4b4.Te6edf3broadcastConnectionTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffstartConnectTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// Do our startup init
Tff7b72try Tb4b4b4{
Te6edf3connectTimeMsec Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)
Te6edf3startConfigOnlyTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3InvalidProtocolBufferExceptionTb4b4b4) Tb4b4b4{
Te6edf3errormsgTb4b4b4(Ta5d6ff"Ta5d6ffInvalid protocol buffer sent by device - update device software and try againTa5d6ff"Tb4b4b4, Te6edf3exTb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3RadioNotConnectedExceptionTb4b4b4) Tb4b4b4{
T8b949e// note: no need to call startDeviceSleep(), because this exception could only have
T8b949e// reached us if it was
T8b949e// already called
Te6edf3errormsgTb4b4b4(Ta5d6ff"Ta5d6ffLost connection to radio during init - waiting for reconnect Tffd700${Te6edf3exTb4b4b4.Te6edf3messageTffd700}Ta5d6ff"Tb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3RemoteExceptionTb4b4b4) Tb4b4b4{
T8b949e// It seems that when the ESP32 goes offline it can briefly come back for a 100ms
T8b949e// ish which
T8b949e// causes the phone to try and reconnect. If we fail downloading our initial radio
T8b949e// state we don't want
T8b949e// to
T8b949e// claim we have a valid connection still
Te6edf3connectionState Tff7b72= Te6edf3ConnectionStateTb4b4b4.Te6edf3DEVICE_SLEEP
Te6edf3startDeviceSleepTb4b4b4(Tb4b4b4)
Tff7b72throw Te6edf3ex T8b949e// Important to rethrow so that we don't tell the app all is well
Tb4b4b4}
Tb4b4b4}
T8b949e// Cancel any existing timeouts
Te6edf3sleepTimeoutTff7b72?.Te6edf3let Tb4b4b4{
Tffa657itTb4b4b4.Te6edf3cancelTb4b4b4(Tb4b4b4)
Te6edf3sleepTimeout Tff7b72= Tff7b72null
Tb4b4b4}
Te6edf3connectionState Tff7b72= Te6edf3c
Tff7b72when Tb4b4b4(Te6edf3cTb4b4b4) Tb4b4b4{
Te6edf3ConnectionStateTb4b4b4.Te6edf3CONNECTED Tff7b72-Tff7b72> Te6edf3startConnectTb4b4b4(Tb4b4b4)
Te6edf3ConnectionStateTb4b4b4.Te6edf3DEVICE_SLEEP Tff7b72-Tff7b72> Te6edf3startDeviceSleepTb4b4b4(Tb4b4b4)
Te6edf3ConnectionStateTb4b4b4.Te6edf3DISCONNECTED Tff7b72-Tff7b72> Te6edf3startDisconnectTb4b4b4(Tb4b4b4)
Tb4b4b4}
T8b949e// Update the android notification in the status bar
Te6edf3maybeUpdateServiceStatusNotificationTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffmaybeUpdateServiceStatusNotificationTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72var Te6edf3update Tff7b72= Tff7b72false
Tff7b72val Te6edf3currentSummary Tff7b72= Te6edf3notificationSummary
Tff7b72val Te6edf3currentStats Tff7b72= Te6edf3localStats
Tff7b72val Te6edf3currentStatsUpdatedAtMillis Tff7b72= Te6edf3localStatsUpdatedAtMillis
Tff7b72if Tb4b4b4(Te6edf3currentSummaryTb4b4b4.Te6edf3isNotBlankTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Tb4b4b4(Te6edf3previousSummary Tff7b72=Tff7b72= Tff7b72null Tff7b72|Tff7b72| Tff7b72!Te6edf3previousSummaryTb4b4b4.Te6edf3equalsTb4b4b4(Te6edf3currentSummaryTb4b4b4)Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3previousSummary Tff7b72= Te6edf3currentSummary
Te6edf3update Tff7b72= Tff7b72true
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3currentStats Tff7b72!Tff7b72= Tff7b72null Tff7b72&Tff7b72& Tb4b4b4(Te6edf3previousStats Tff7b72=Tff7b72= Tff7b72null Tff7b72|Tff7b72| Tff7b72!Tb4b4b4(Te6edf3previousStatsTff7b72?.Te6edf3equalsTb4b4b4(Te6edf3currentStatsTb4b4b4) Tff7b72?: Tff7b72falseTb4b4b4)Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3previousStats Tff7b72= Te6edf3currentStats
Te6edf3update Tff7b72= Tff7b72true
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3updateTb4b4b4) Tb4b4b4{
Te6edf3serviceNotificationsTb4b4b4.Te6edf3updateServiceStateNotificationTb4b4b4(
Te6edf3summaryString Tff7b72= Te6edf3currentSummaryTb4b4b4,
Te6edf3localStats Tff7b72= Te6edf3currentStatsTb4b4b4,
Te6edf3currentStatsUpdatedAtMillis Tff7b72= Te6edf3currentStatsUpdatedAtMillisTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffonRadioConnectionStateTb4b4b4(Te6edf3stateTb4b4b4: Te6edf3RadioServiceConnectionStateTb4b4b4) Tb4b4b4{
T8b949e// sleep now disabled by default on ESP32, permanent is true unless light sleep enabled
Tff7b72val Te6edf3isRouter Tff7b72= Te6edf3localConfigTb4b4b4.Te6edf3deviceTb4b4b4.Te6edf3role Tff7b72=Tff7b72= Te6edf3ConfigProtosTb4b4b4.Te6edf3ConfigTb4b4b4.Te6edf3DeviceConfigTb4b4b4.Te6edf3RoleTb4b4b4.Te6edf3ROUTER
Tff7b72val Te6edf3lsEnabled Tff7b72= Te6edf3localConfigTb4b4b4.Te6edf3powerTb4b4b4.Te6edf3isPowerSaving Tff7b72|Tff7b72| Te6edf3isRouter
Tff7b72val Te6edf3connected Tff7b72= Te6edf3stateTb4b4b4.Te6edf3isConnected
Tff7b72val Te6edf3permanent Tff7b72= Te6edf3stateTb4b4b4.Te6edf3isPermanent Tff7b72|Tff7b72| Tff7b72!Te6edf3lsEnabled
Te6edf3onConnectionChangedTb4b4b4(
Tff7b72when Tb4b4b4{
Te6edf3connected Tff7b72-Tff7b72> Te6edf3ConnectionStateTb4b4b4.Te6edf3CONNECTED
Te6edf3permanent Tff7b72-Tff7b72> Te6edf3ConnectionStateTb4b4b4.Te6edf3DISCONNECTED
Tff7b72else Tff7b72-Tff7b72> Te6edf3ConnectionStateTb4b4b4.Te6edf3DEVICE_SLEEP
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3packetHandlersTb4b4b4: Te6edf3MapTff7b72<Te6edf3PayloadVariantCaseTb4b4b4, Tb4b4b4(Tb4b4b4(Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadioTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4)Tff7b72> Tff7b72by Te6edf3lazy Tb4b4b4{
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3entriesTb4b4b4.Te6edf3associateWith Tb4b4b4{ Te6edf3variantTb4b4b4: Te6edf3PayloadVariantCase Tff7b72-Tff7b72>
Tff7b72when Tb4b4b4(Te6edf3variantTb4b4b4) Tb4b4b4{
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3PACKET Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72> Te6edf3handleReceivedMeshPacketTb4b4b4(Te6edf3protoTb4b4b4.Te6edf3packetTb4b4b4) Tb4b4b4}
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3CONFIG_COMPLETE_ID Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72>
Te6edf3handleConfigCompleteTb4b4b4(Te6edf3protoTb4b4b4.Te6edf3configCompleteIdTb4b4b4)
Tb4b4b4}
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3MY_INFO Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72> Te6edf3handleMyInfoTb4b4b4(Te6edf3protoTb4b4b4.Te6edf3myInfoTb4b4b4) Tb4b4b4}
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3NODE_INFO Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72> Te6edf3handleNodeInfoTb4b4b4(Te6edf3protoTb4b4b4.Te6edf3nodeInfoTb4b4b4) Tb4b4b4}
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3CHANNEL Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72> Te6edf3handleChannelTb4b4b4(Te6edf3protoTb4b4b4.Te6edf3channelTb4b4b4) Tb4b4b4}
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3CONFIG Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72> Te6edf3handleDeviceConfigTb4b4b4(Te6edf3protoTb4b4b4.Te6edf3configTb4b4b4) Tb4b4b4}
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3MODULECONFIG Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72>
Te6edf3handleModuleConfigTb4b4b4(Te6edf3protoTb4b4b4.Te6edf3moduleConfigTb4b4b4)
Tb4b4b4}
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3QUEUESTATUS Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72>
Te6edf3packetHandlerTb4b4b4.Te6edf3handleQueueStatusTb4b4b4(Tb4b4b4(Te6edf3protoTb4b4b4.Te6edf3queueStatusTb4b4b4)Tb4b4b4)
Tb4b4b4}
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3METADATA Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72> Te6edf3handleMetadataTb4b4b4(Te6edf3protoTb4b4b4.Te6edf3metadataTb4b4b4) Tb4b4b4}
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3MQTTCLIENTPROXYMESSAGE Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72>
Te6edf3handleMqttProxyMessageTb4b4b4(Te6edf3protoTb4b4b4.Te6edf3mqttClientProxyMessageTb4b4b4)
Tb4b4b4}
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3DEVICEUICONFIG Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72>
Te6edf3handleDeviceUiConfigTb4b4b4(Te6edf3protoTb4b4b4.Te6edf3deviceuiConfigTb4b4b4)
Tb4b4b4}
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3FILEINFO Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72> Te6edf3handleFileInfoTb4b4b4(Te6edf3protoTb4b4b4.Te6edf3fileInfoTb4b4b4) Tb4b4b4}
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3CLIENTNOTIFICATION Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72>
Te6edf3handleClientNotificationTb4b4b4(Te6edf3protoTb4b4b4.Te6edf3clientNotificationTb4b4b4)
Tb4b4b4}
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3LOG_RECORD Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72> Te6edf3handleLogReordTb4b4b4(Te6edf3protoTb4b4b4.Te6edf3logRecordTb4b4b4) Tb4b4b4}
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3REBOOTED Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72> Te6edf3handleRebootedTb4b4b4(Te6edf3protoTb4b4b4.Te6edf3rebootedTb4b4b4) Tb4b4b4}
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3XMODEMPACKET Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3protoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadio Tff7b72-Tff7b72>
Te6edf3handleXmodemPacketTb4b4b4(Te6edf3protoTb4b4b4.Te6edf3xmodemPacketTb4b4b4)
Tb4b4b4}
T8b949e// Explicitly handle default/unwanted cases to satisfy the exhaustive `when`
Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3PAYLOADVARIANT_NOT_SET Tff7b72-Tff7b72> Tb4b4b4{ Te6edf3proto Tff7b72-Tff7b72>
Te6edf3errormsgTb4b4b4(Ta5d6ff"Ta5d6ffUnexpected or unrecognized FromRadio variant: Tffd700${Te6edf3protoTb4b4b4.Te6edf3payloadVariantCaseTffd700}Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Te6edf3MeshProtosTb4b4b4.Td2a8ffFromRadioTb4b4b4.Te6edf3routeTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3packetHandlersTff7b72[Tff7b72thisTb4b4b4.Te6edf3payloadVariantCaseTff7b72]Tff7b72?.Te6edf3invokeTb4b4b4(Tff7b72thisTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffonReceiveFromRadioTb4b4b4(Te6edf3bytesTb4b4b4: Te6edf3ByteArrayTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72val Te6edf3proto Tff7b72= Te6edf3MeshProtosTb4b4b4.Te6edf3FromRadioTb4b4b4.Te6edf3parseFromTb4b4b4(Te6edf3bytesTb4b4b4)
Te6edf3protoTb4b4b4.Te6edf3routeTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3InvalidProtocolBufferExceptionTb4b4b4) Tb4b4b4{
Te6edf3errormsgTb4b4b4(Ta5d6ff"Ta5d6ffInvalid Protobuf from radio, len=Tffd700${Te6edf3bytesTb4b4b4.Te6edf3sizeTffd700}Ta5d6ff"Tb4b4b4, Te6edf3exTb4b4b4)
Tb4b4b4}
Tb4b4b4}
T8b949e// A provisional MyNodeInfo that we will install if all of our node config downloads go okay
Tff7b72private Tff7b72var Te6edf3newMyNodeInfoTb4b4b4: Te6edf3MyNodeEntity? Tff7b72= Tff7b72null
T8b949e// provisional NodeInfos we will install if all goes well
Tff7b72private Tff7b72val Te6edf3newNodes Tff7b72= Te6edf3mutableListOfTff7b72<Te6edf3MeshProtosTb4b4b4.Te6edf3NodeInfoTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72fun Td2a8ffhandleDeviceConfigTb4b4b4(Te6edf3configTb4b4b4: Te6edf3ConfigProtosTb4b4b4.Te6edf3ConfigTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived config Tffd700${Te6edf3configTb4b4b4.Te6edf3toOneLineStringTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3UUIDTb4b4b4.Te6edf3randomUUIDTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffConfig Tffd700${Te6edf3configTb4b4b4.Te6edf3payloadVariantCaseTffd700}Ta5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3raw_message Tff7b72= Te6edf3configTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3fromRadio Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3config Tff7b72= Te6edf3config Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3insertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Te6edf3setLocalConfigTb4b4b4(Te6edf3configTb4b4b4)
Tff7b72val Te6edf3configCount Tff7b72= Te6edf3localConfigTb4b4b4.Te6edf3allFieldsTb4b4b4.Te6edf3size
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3setStatusMessageTb4b4b4(Ta5d6ff"Ta5d6ffDevice config (Tffd700$Te6edf3configCountTa5d6ff / Tffd700$Te6edf3configTotalTa5d6ff)Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhandleModuleConfigTb4b4b4(Te6edf3configTb4b4b4: Te6edf3ModuleConfigProtosTb4b4b4.Te6edf3ModuleConfigTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived moduleConfig Tffd700${Te6edf3configTb4b4b4.Te6edf3toOneLineStringTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3UUIDTb4b4b4.Te6edf3randomUUIDTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffModuleConfig Tffd700${Te6edf3configTb4b4b4.Te6edf3payloadVariantCaseTffd700}Ta5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3raw_message Tff7b72= Te6edf3configTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3fromRadio Tb4b4b4{ Te6edf3moduleConfig Tff7b72= Te6edf3config Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3insertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Te6edf3setLocalModuleConfigTb4b4b4(Te6edf3configTb4b4b4)
Tff7b72val Te6edf3moduleCount Tff7b72= Te6edf3moduleConfigTb4b4b4.Te6edf3allFieldsTb4b4b4.Te6edf3size
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3setStatusMessageTb4b4b4(Ta5d6ff"Ta5d6ffModule config (Tffd700$Te6edf3moduleCountTa5d6ff / Tffd700$Te6edf3moduleTotalTa5d6ff)Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhandleChannelTb4b4b4(Te6edf3chTb4b4b4: Te6edf3ChannelProtosTb4b4b4.Te6edf3ChannelTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived channel Tffd700${Te6edf3chTb4b4b4.Te6edf3indexTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3UUIDTb4b4b4.Te6edf3randomUUIDTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffChannelTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3raw_message Tff7b72= Te6edf3chTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3fromRadio Tb4b4b4{ Te6edf3channel Tff7b72= Te6edf3ch Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3insertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3chTb4b4b4.Te6edf3role Tff7b72!Tff7b72= Te6edf3ChannelProtosTb4b4b4.Te6edf3ChannelTb4b4b4.Te6edf3RoleTb4b4b4.Te6edf3DISABLEDTb4b4b4) Te6edf3updateChannelSettingsTb4b4b4(Te6edf3chTb4b4b4)
Tff7b72val Te6edf3maxChannels Tff7b72= Te6edf3myNodeInfoTff7b72?.Te6edf3maxChannels Tff7b72?: T79c0ff8
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3setStatusMessageTb4b4b4(Ta5d6ff"Ta5d6ffChannels (Tffd700${Te6edf3chTb4b4b4.Te6edf3index Tff7b72+ T79c0ff1Tffd700}Ta5d6ff / Tffd700$Te6edf3maxChannelsTa5d6ff)Ta5d6ff"Tb4b4b4)
Tb4b4b4}
T8b949e/** Convert a protobuf NodeInfo into our model objects and update our node DB */
Tff7b72private Tff7b72fun Td2a8ffinstallNodeInfoTb4b4b4(Te6edf3infoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3NodeInfoTb4b4b4) Tb4b4b4{
T8b949e// Just replace/add any entry
Te6edf3updateNodeInfoTb4b4b4(Te6edf3infoTb4b4b4.Te6edf3numTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3infoTb4b4b4.Te6edf3hasUserTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tffa657itTb4b4b4.Te6edf3user Tff7b72=
Te6edf3infoTb4b4b4.Te6edf3userTb4b4b4.Te6edf3copy Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3isLicensedTb4b4b4) Te6edf3clearPublicKeyTb4b4b4(Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3infoTb4b4b4.Te6edf3viaMqttTb4b4b4) Te6edf3longName Tff7b72= Ta5d6ff"Tffd700$Te6edf3longNameTa5d6ff (MQTT)Ta5d6ff"
Tb4b4b4}
Tffa657itTb4b4b4.Te6edf3longName Tff7b72= Tffa657itTb4b4b4.Te6edf3userTb4b4b4.Te6edf3longName
Tffa657itTb4b4b4.Te6edf3shortName Tff7b72= Tffa657itTb4b4b4.Te6edf3userTb4b4b4.Te6edf3shortName
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3infoTb4b4b4.Te6edf3hasPositionTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tffa657itTb4b4b4.Te6edf3position Tff7b72= Te6edf3infoTb4b4b4.Te6edf3position
Tffa657itTb4b4b4.Te6edf3latitude Tff7b72= Te6edf3PositionTb4b4b4.Te6edf3degDTb4b4b4(Te6edf3infoTb4b4b4.Te6edf3positionTb4b4b4.Te6edf3latitudeITb4b4b4)
Tffa657itTb4b4b4.Te6edf3longitude Tff7b72= Te6edf3PositionTb4b4b4.Te6edf3degDTb4b4b4(Te6edf3infoTb4b4b4.Te6edf3positionTb4b4b4.Te6edf3longitudeITb4b4b4)
Tb4b4b4}
Tffa657itTb4b4b4.Te6edf3lastHeard Tff7b72= Te6edf3infoTb4b4b4.Te6edf3lastHeard
Tff7b72if Tb4b4b4(Te6edf3infoTb4b4b4.Te6edf3hasDeviceMetricsTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tffa657itTb4b4b4.Te6edf3deviceTelemetry Tff7b72= Te6edf3telemetry Tb4b4b4{ Te6edf3deviceMetrics Tff7b72= Te6edf3infoTb4b4b4.Te6edf3deviceMetrics Tb4b4b4}
Tb4b4b4}
Tffa657itTb4b4b4.Te6edf3channel Tff7b72= Te6edf3infoTb4b4b4.Te6edf3channel
Tffa657itTb4b4b4.Te6edf3viaMqtt Tff7b72= Te6edf3infoTb4b4b4.Te6edf3viaMqtt
T8b949e// hopsAway should be nullable/optional from the proto, but explicitly checking it's
T8b949e// existence first
Tffa657itTb4b4b4.Te6edf3hopsAway Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3infoTb4b4b4.Te6edf3hasHopsAwayTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3infoTb4b4b4.Te6edf3hopsAway
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72-T79c0ff1
Tb4b4b4}
Tffa657itTb4b4b4.Te6edf3isFavorite Tff7b72= Te6edf3infoTb4b4b4.Te6edf3isFavorite
Tffa657itTb4b4b4.Te6edf3isIgnored Tff7b72= Te6edf3infoTb4b4b4.Te6edf3isIgnored
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhandleNodeInfoTb4b4b4(Te6edf3infoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3NodeInfoTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(
Ta5d6ff"Ta5d6ffReceived nodeinfo num=Tffd700${Te6edf3infoTb4b4b4.Te6edf3numTffd700}Ta5d6ff,Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ff hasUser=Tffd700${Te6edf3infoTb4b4b4.Te6edf3hasUserTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff,Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ff hasPosition=Tffd700${Te6edf3infoTb4b4b4.Te6edf3hasPositionTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff,Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ff hasDeviceMetrics=Tffd700${Te6edf3infoTb4b4b4.Te6edf3hasDeviceMetricsTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3UUIDTb4b4b4.Te6edf3randomUUIDTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffNodeInfoTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3raw_message Tff7b72= Te6edf3infoTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3fromRadio Tb4b4b4{ Te6edf3nodeInfo Tff7b72= Te6edf3info Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3insertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Te6edf3newNodesTb4b4b4.Te6edf3addTb4b4b4(Te6edf3infoTb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3setStatusMessageTb4b4b4(Ta5d6ff"Ta5d6ffNodes (Tffd700${Te6edf3newNodesTb4b4b4.Te6edf3sizeTffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72var Te6edf3rawMyNodeInfoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3MyNodeInfoTff7b72? Tff7b72= Tff7b72null
T8b949e/**
* Regenerate the myNodeInfo model. We call this twice. Once after we receive myNodeInfo from the device and again
* after we have the node DB (which might allow us a better notion of our HwModel.
*/
Tff7b72private Tff7b72fun Td2a8ffregenMyNodeInfoTb4b4b4(Te6edf3metadataTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3DeviceMetadataTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3myInfo Tff7b72= Te6edf3rawMyNodeInfo
Tff7b72if Tb4b4b4(Te6edf3myInfo Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3mi Tff7b72=
Te6edf3withTb4b4b4(Te6edf3myInfoTb4b4b4) Tb4b4b4{
Te6edf3MyNodeEntityTb4b4b4(
Te6edf3myNodeNum Tff7b72= Te6edf3myNodeNumTb4b4b4,
Te6edf3model Tff7b72=
Tff7b72when Tb4b4b4(Tff7b72val Te6edf3hwModel Tff7b72= Te6edf3metadataTb4b4b4.Te6edf3hwModelTb4b4b4) Tb4b4b4{
Tff7b72nullTb4b4b4,
Te6edf3MeshProtosTb4b4b4.Te6edf3HardwareModelTb4b4b4.Te6edf3UNSETTb4b4b4,
Tff7b72-Tff7b72> Tff7b72null
Tff7b72else Tff7b72-Tff7b72> Te6edf3hwModelTb4b4b4.Te6edf3nameTb4b4b4.Te6edf3replaceTb4b4b4(Ta5d6ff'_'Tb4b4b4, Ta5d6ff'-'Tb4b4b4)Tb4b4b4.Te6edf3replaceTb4b4b4(Ta5d6ff'p'Tb4b4b4, Ta5d6ff'.'Tb4b4b4)Tb4b4b4.Te6edf3lowercaseTb4b4b4(Tb4b4b4)
Tb4b4b4}Tb4b4b4,
Te6edf3firmwareVersion Tff7b72= Te6edf3metadataTb4b4b4.Te6edf3firmwareVersionTb4b4b4,
Te6edf3couldUpdate Tff7b72= Tff7b72falseTb4b4b4,
Te6edf3shouldUpdate Tff7b72= Tff7b72falseTb4b4b4, T8b949e// TODO add check after re-implementing firmware updates
Te6edf3currentPacketId Tff7b72= Te6edf3currentPacketId Te6edf3and T79c0ff0Te6edf3xffffffffLTb4b4b4,
Te6edf3messageTimeoutMsec Tff7b72= T79c0ff5 Tff7b72* T79c0ff6T79c0ff0 Tff7b72* T79c0ff1T79c0ff0T79c0ff0T79c0ff0Tb4b4b4, T8b949e// constants from current firmware code
Te6edf3minAppVersion Tff7b72= Te6edf3minAppVersionTb4b4b4,
Te6edf3maxChannels Tff7b72= T79c0ff8Tb4b4b4,
Te6edf3hasWifi Tff7b72= Te6edf3metadataTb4b4b4.Te6edf3hasWifiTb4b4b4,
Te6edf3deviceId Tff7b72= Te6edf3deviceIdTb4b4b4.Te6edf3toStringUtf8Tb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{ Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3insertMetadataTb4b4b4(Te6edf3miTb4b4b4.Te6edf3myNodeNumTb4b4b4, Te6edf3metadataTb4b4b4) Tb4b4b4}
Te6edf3newMyNodeInfo Tff7b72= Te6edf3mi
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffsendAnalyticsTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3myInfo Tff7b72= Te6edf3rawMyNodeInfo
Tff7b72val Te6edf3mi Tff7b72= Te6edf3myNodeInfo
Tff7b72if Tb4b4b4(Te6edf3myInfo Tff7b72!Tff7b72= Tff7b72null Tff7b72&Tff7b72& Te6edf3mi Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
T8b949e// Track types of devices and firmware versions in use
Te6edf3GeeksvilleApplicationTb4b4b4.Te6edf3analyticsTb4b4b4.Te6edf3setUserInfoTb4b4b4(
Te6edf3DataPairTb4b4b4(Ta5d6ff"Ta5d6fffirmwareTa5d6ff"Tb4b4b4, Te6edf3miTb4b4b4.Te6edf3firmwareVersionTb4b4b4)Tb4b4b4,
Te6edf3DataPairTb4b4b4(Ta5d6ff"Ta5d6ffhw_modelTa5d6ff"Tb4b4b4, Te6edf3miTb4b4b4.Te6edf3modelTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
T8b949e/** Update MyNodeInfo (called from either new API version or the old one) */
Tff7b72private Tff7b72fun Td2a8ffhandleMyInfoTb4b4b4(Te6edf3myInfoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3MyNodeInfoTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3UUIDTb4b4b4.Te6edf3randomUUIDTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffMyNodeInfoTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3raw_message Tff7b72= Te6edf3myInfoTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3fromRadio Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3myInfo Tff7b72= Te6edf3myInfo Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3insertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Te6edf3rawMyNodeInfo Tff7b72= Te6edf3myInfo
T8b949e// We'll need to get a new set of channels and settings now
Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3clearChannelSetTb4b4b4(Tb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3clearLocalConfigTb4b4b4(Tb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3clearLocalModuleConfigTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
T8b949e/** Update our DeviceMetadata */
Tff7b72private Tff7b72fun Td2a8ffhandleMetadataTb4b4b4(Te6edf3metadataTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3DeviceMetadataTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived deviceMetadata Tffd700${Te6edf3metadataTb4b4b4.Te6edf3toOneLineStringTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3UUIDTb4b4b4.Te6edf3randomUUIDTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffDeviceMetadataTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3raw_message Tff7b72= Te6edf3metadataTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3fromRadio Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3metadata Tff7b72= Te6edf3metadata Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3insertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Te6edf3regenMyNodeInfoTb4b4b4(Te6edf3metadataTb4b4b4)
Tb4b4b4}
T8b949e/** Publish MqttClientProxyMessage (fromRadio) */
Tff7b72private Tff7b72fun Td2a8ffhandleMqttProxyMessageTb4b4b4(Te6edf3messageTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3MqttClientProxyMessageTb4b4b4) Tb4b4b4{
Te6edf3withTb4b4b4(Te6edf3messageTb4b4b4) Tb4b4b4{
Tff7b72when Tb4b4b4(Te6edf3payloadVariantCaseTb4b4b4) Tb4b4b4{
Te6edf3MeshProtosTb4b4b4.Te6edf3MqttClientProxyMessageTb4b4b4.Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3TEXT Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3mqttRepositoryTb4b4b4.Te6edf3publishTb4b4b4(Te6edf3topicTb4b4b4, Te6edf3textTb4b4b4.Te6edf3encodeToByteArrayTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3retainedTb4b4b4)
Tb4b4b4}
Te6edf3MeshProtosTb4b4b4.Te6edf3MqttClientProxyMessageTb4b4b4.Te6edf3PayloadVariantCaseTb4b4b4.Te6edf3DATA Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3mqttRepositoryTb4b4b4.Te6edf3publishTb4b4b4(Te6edf3topicTb4b4b4, Te6edf3dataTb4b4b4.Te6edf3toByteArrayTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3retainedTb4b4b4)
Tb4b4b4}
Tff7b72else Tff7b72-Tff7b72> Tb4b4b4{Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhandleClientNotificationTb4b4b4(Te6edf3notificationTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3ClientNotificationTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived clientNotification Tffd700${Te6edf3notificationTb4b4b4.Te6edf3toOneLineStringTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3setClientNotificationTb4b4b4(Te6edf3notificationTb4b4b4)
Te6edf3serviceNotificationsTb4b4b4.Te6edf3showClientNotificationTb4b4b4(Te6edf3notificationTb4b4b4)
T8b949e// if the future for the originating request is still in the queue, complete as unsuccessful
T8b949e// for now
Te6edf3packetHandlerTb4b4b4.Te6edf3removeResponseTb4b4b4(Te6edf3notificationTb4b4b4.Te6edf3replyIdTb4b4b4, Te6edf3complete Tff7b72= Tff7b72falseTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhandleFileInfoTb4b4b4(Te6edf3fileInfoTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3FileInfoTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived fileInfo Tffd700${Te6edf3fileInfoTb4b4b4.Te6edf3toOneLineStringTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3UUIDTb4b4b4.Te6edf3randomUUIDTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffFileInfoTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3raw_message Tff7b72= Te6edf3fileInfoTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3fromRadio Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3fileInfo Tff7b72= Te6edf3fileInfo Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3insertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhandleLogReordTb4b4b4(Te6edf3logRecordTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3LogRecordTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived logRecord Tffd700${Te6edf3logRecordTb4b4b4.Te6edf3toOneLineStringTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3UUIDTb4b4b4.Te6edf3randomUUIDTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffLogRecordTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3raw_message Tff7b72= Te6edf3logRecordTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3fromRadio Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3logRecord Tff7b72= Te6edf3logRecord Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3insertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhandleRebootedTb4b4b4(Te6edf3rebootedTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived rebooted Tffd700${Te6edf3rebootedTb4b4b4.Te6edf3toOneLineStringTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3UUIDTb4b4b4.Te6edf3randomUUIDTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffRebootedTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3raw_message Tff7b72= Te6edf3rebootedTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3fromRadio Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3rebooted Tff7b72= Te6edf3rebooted Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3insertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhandleXmodemPacketTb4b4b4(Te6edf3xmodemPacketTb4b4b4: Te6edf3XmodemProtosTb4b4b4.Te6edf3XModemTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived XmodemPacket Tffd700${Te6edf3xmodemPacketTb4b4b4.Te6edf3toOneLineStringTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3UUIDTb4b4b4.Te6edf3randomUUIDTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffXmodemPacketTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3raw_message Tff7b72= Te6edf3xmodemPacketTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3fromRadio Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3xmodemPacket Tff7b72= Te6edf3xmodemPacket Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3insertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhandleDeviceUiConfigTb4b4b4(Te6edf3deviceuiConfigTb4b4b4: Te6edf3DeviceUIProtosTb4b4b4.Te6edf3DeviceUIConfigTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived deviceUIConfig Tffd700${Te6edf3deviceuiConfigTb4b4b4.Te6edf3toOneLineStringTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3UUIDTb4b4b4.Te6edf3randomUUIDTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffDeviceUIConfigTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3raw_message Tff7b72= Te6edf3deviceuiConfigTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3fromRadio Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3deviceuiConfig Tff7b72= Te6edf3deviceuiConfig Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3insertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4)
Tb4b4b4}
T8b949e/** Connect, subscribe and receive Flow of MqttClientProxyMessage (toRadio) */
Tff7b72private Tff7b72fun Td2a8ffstartMqttClientProxyTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3mqttMessageFlowTff7b72?.Te6edf3isActive Tff7b72=Tff7b72= Tff7b72trueTb4b4b4) Tff7b72return
Tff7b72if Tb4b4b4(Te6edf3moduleConfigTb4b4b4.Te6edf3mqttTb4b4b4.Te6edf3enabled Tff7b72&Tff7b72& Te6edf3moduleConfigTb4b4b4.Te6edf3mqttTb4b4b4.Te6edf3proxyToClientEnabledTb4b4b4) Tb4b4b4{
Te6edf3mqttMessageFlow Tff7b72=
Te6edf3mqttRepositoryTb4b4b4.Te6edf3proxyMessageFlow
Tb4b4b4.Te6edf3onEach Tb4b4b4{ Te6edf3message Tff7b72-Tff7b72>
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(Te6edf3ToRadioTb4b4b4.Te6edf3newBuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Te6edf3mqttClientProxyMessage Tff7b72= Te6edf3message Tb4b4b4}Tb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3catch Tb4b4b4{ Te6edf3throwable Tff7b72-Tff7b72> Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3setErrorMessageTb4b4b4(Ta5d6ff"Ta5d6ffMqttClientProxy failed: Tffd700$Te6edf3throwableTa5d6ff"Tb4b4b4) Tb4b4b4}
Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3serviceScopeTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffstopMqttClientProxyTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3mqttMessageFlowTff7b72?.Te6edf3isActive Tff7b72=Tff7b72= Tff7b72trueTb4b4b4) Tb4b4b4{
Te6edf3infoTb4b4b4(Ta5d6ff"Ta5d6ffStopping MqttClientProxyTa5d6ff"Tb4b4b4)
Te6edf3mqttMessageFlowTff7b72?.Te6edf3cancelTb4b4b4(Tb4b4b4)
Te6edf3mqttMessageFlow Tff7b72= Tff7b72null
Tb4b4b4}
Tb4b4b4}
T8b949e// If we've received our initial config, our radio settings and all of our channels, send any
T8b949e// queued packets and
T8b949e// broadcast connected to clients
Tff7b72private Tff7b72fun Td2a8ffonHasSettingsTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3processQueuedPacketsTb4b4b4(Tb4b4b4) T8b949e// send any packets that were queued up
Te6edf3startMqttClientProxyTb4b4b4(Tb4b4b4)
Te6edf3serviceBroadcastsTb4b4b4.Te6edf3broadcastConnectionTb4b4b4(Tb4b4b4)
Te6edf3sendAnalyticsTb4b4b4(Tb4b4b4)
Te6edf3reportConnectionTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhandleConfigCompleteTb4b4b4(Te6edf3configCompleteIdTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3configCompleteId Tff7b72=Tff7b72= Te6edf3CONFIG_ONLY_NONCETb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived config complete for config-only nonce Tffd700$Te6edf3CONFIG_ONLY_NONCETa5d6ff"Tb4b4b4)
Te6edf3handleConfigOnlyCompleteTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3configCompleteId Tff7b72=Tff7b72= Te6edf3NODE_INFO_ONLY_NONCETb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived node info complete for nonce Tffd700$Te6edf3NODE_INFO_ONLY_NONCETa5d6ff"Tb4b4b4)
Te6edf3handleNodeInfoCompleteTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3warnTb4b4b4(Ta5d6ff"Ta5d6ffReceived unexpected config complete id Tffd700$Te6edf3configCompleteIdTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhandleConfigOnlyCompleteTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived config only complete for nonce Tffd700$Te6edf3CONFIG_ONLY_NONCETa5d6ff"Tb4b4b4)
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3UUIDTb4b4b4.Te6edf3randomUUIDTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffConfigOnlyCompleteTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3raw_message Tff7b72= Te6edf3CONFIG_ONLY_NONCETb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3fromRadio Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3configCompleteId Tff7b72= Te6edf3CONFIG_ONLY_NONCE Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3insertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4)
T8b949e// This was our config request
Tff7b72if Tb4b4b4(Te6edf3newMyNodeInfo Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3errormsgTb4b4b4(Ta5d6ff"Ta5d6ffDid not receive a valid configTa5d6ff"Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3myNodeInfo Tff7b72= Te6edf3newMyNodeInfo
Tb4b4b4}
Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
Te6edf3delayTb4b4b4(Te6edf3CONFIG_WAIT_MSTb4b4b4)
Te6edf3radioInterfaceServiceTb4b4b4.Te6edf3keepAliveTb4b4b4(Tb4b4b4)
Te6edf3delayTb4b4b4(Te6edf3CONFIG_WAIT_MSTb4b4b4)
Tb4b4b4}
Te6edf3startNodeInfoOnlyTb4b4b4(Tb4b4b4)
Te6edf3onHasSettingsTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffhandleNodeInfoCompleteTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffReceived node info complete for nonce Tffd700$Te6edf3NODE_INFO_ONLY_NONCETa5d6ff"Tb4b4b4)
Tff7b72val Te6edf3packetToSave Tff7b72=
Te6edf3MeshLogTb4b4b4(
Te6edf3uuid Tff7b72= Te6edf3UUIDTb4b4b4.Te6edf3randomUUIDTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message_type Tff7b72= Ta5d6ff"Ta5d6ffNodeInfoCompleteTa5d6ff"Tb4b4b4,
Te6edf3received_date Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3raw_message Tff7b72= Te6edf3NODE_INFO_ONLY_NONCETb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3fromRadio Tff7b72= Te6edf3fromRadio Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3configCompleteId Tff7b72= Te6edf3NODE_INFO_ONLY_NONCE Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Te6edf3insertMeshLogTb4b4b4(Te6edf3packetToSaveTb4b4b4)
T8b949e// This was our config request
Tff7b72if Tb4b4b4(Te6edf3newNodesTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3errormsgTb4b4b4(Ta5d6ff"Ta5d6ffDid not receive a valid node infoTa5d6ff"Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3newNodesTb4b4b4.Te6edf3forEachTb4b4b4(Tff7b72::Te6edf3installNodeInfoTb4b4b4)
Te6edf3newNodesTb4b4b4.Te6edf3clearTb4b4b4(Tb4b4b4) T8b949e// Just to save RAM ;-)
Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3installMyNodeInfoTb4b4b4(Te6edf3myNodeInfoTff7b72!!Tb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3installNodeDbTb4b4b4(Te6edf3nodeDBbyNodeNumTb4b4b4.Te6edf3valuesTb4b4b4.Te6edf3toListTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Te6edf3haveNodeDB Tff7b72= Tff7b72true T8b949e// we now have nodes from real hardware
Te6edf3sendAnalyticsTb4b4b4(Tb4b4b4)
Te6edf3onNodeDBChangedTb4b4b4(Tb4b4b4)
Tb4b4b4}
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(Te6edf3newMeshPacketToTb4b4b4(Te6edf3myNodeNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacket Tb4b4b4{ Te6edf3setTimeOnly Tff7b72= Te6edf3currentSecondTb4b4b4(Tb4b4b4) Tb4b4b4}Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
T8b949e/** Start the modern (REV2) API configuration flow */
Tff7b72private Tff7b72fun Td2a8ffstartConfigOnlyTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3newMyNodeInfo Tff7b72= Tff7b72null
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffStarting config only nonce=Tffd700$Te6edf3CONFIG_ONLY_NONCETa5d6ff"Tb4b4b4)
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(Te6edf3ToRadioTb4b4b4.Te6edf3newBuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3wantConfigId Tff7b72= Te6edf3CONFIG_ONLY_NONCE Tb4b4b4}Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffstartNodeInfoOnlyTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3newNodesTb4b4b4.Te6edf3clearTb4b4b4(Tb4b4b4)
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffStarting node info nonce=Tffd700$Te6edf3NODE_INFO_ONLY_NONCETa5d6ff"Tb4b4b4)
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(Te6edf3ToRadioTb4b4b4.Te6edf3newBuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Tff7b72thisTb4b4b4.Te6edf3wantConfigId Tff7b72= Te6edf3NODE_INFO_ONLY_NONCE Tb4b4b4}Tb4b4b4)
Tb4b4b4}
T8b949e/** Send a position (typically from our built in GPS) into the mesh. */
Tff7b72private Tff7b72fun Td2a8ffsendPositionTb4b4b4(Te6edf3positionTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3PositionTb4b4b4, Te6edf3destNumTb4b4b4: Tffa657Int? Tff7b72= Tff7b72nullTb4b4b4, Te6edf3wantResponseTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72falseTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72val Te6edf3mi Tff7b72= Te6edf3myNodeInfo
Tff7b72if Tb4b4b4(Te6edf3mi Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3idNum Tff7b72= Te6edf3destNum Tff7b72?: Te6edf3miTb4b4b4.Te6edf3myNodeNum T8b949e// when null we just send to the local node
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffSending our position/time to=Tffd700$Te6edf3idNumTa5d6ff Tffd700${Te6edf3PositionTb4b4b4(Te6edf3positionTb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
T8b949e// Also update our own map for our nodeNum, by handling the packet just like packets
T8b949e// from other users
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3localConfigTb4b4b4.Te6edf3positionTb4b4b4.Te6edf3fixedPositionTb4b4b4) Tb4b4b4{
Te6edf3handleReceivedPositionTb4b4b4(Te6edf3miTb4b4b4.Te6edf3myNodeNumTb4b4b4, Te6edf3positionTb4b4b4)
Tb4b4b4}
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3idNumTb4b4b4)Tb4b4b4.Te6edf3buildMeshPacketTb4b4b4(
Te6edf3channel Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3destNum Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
T79c0ff0
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3nodeDBbyNodeNumTff7b72[Te6edf3destNumTff7b72]Tff7b72?.Te6edf3channel Tff7b72?: T79c0ff0
Tb4b4b4}Tb4b4b4,
Te6edf3priority Tff7b72= Te6edf3MeshPacketTb4b4b4.Te6edf3PriorityTb4b4b4.Te6edf3BACKGROUNDTb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3portnumValue Tff7b72= Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3POSITION_APP_VALUE
Te6edf3payload Tff7b72= Te6edf3positionTb4b4b4.Te6edf3toByteStringTb4b4b4(Tb4b4b4)
Tff7b72thisTb4b4b4.Te6edf3wantResponse Tff7b72= Te6edf3wantResponse
Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3BLEExceptionTb4b4b4) Tb4b4b4{
Te6edf3warnTb4b4b4(Ta5d6ff"Ta5d6ffIgnoring disconnected radio during gps location updateTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
T8b949e/** Send setOwner admin packet with [MeshProtos.User] protobuf */
Tff7b72private Tff7b72fun Td2a8ffsetOwnerTb4b4b4(Te6edf3packetIdTb4b4b4: Tffa657IntTb4b4b4, Te6edf3userTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3UserTb4b4b4) Tff7b72= Te6edf3withTb4b4b4(Te6edf3userTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3dest Tff7b72= Te6edf3nodeDBbyIDTff7b72[Te6edf3idTff7b72] Tff7b72?: Tff7b72throw Te6edf3ExceptionTb4b4b4(Ta5d6ff"Ta5d6ffCan't set user without a NodeInfoTa5d6ff"Tb4b4b4) T8b949e// this shouldn't happen
Tff7b72val Te6edf3old Tff7b72= Te6edf3destTb4b4b4.Te6edf3user
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffComplexConditionTa5d6ff"Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3user Tff7b72=Tff7b72= Te6edf3oldTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffIgnoring nop owner changeTa5d6ff"Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3debugTb4b4b4(
Ta5d6ff"Ta5d6ffsetOwner Id: Tffd700$Te6edf3idTa5d6ff longName: Tffd700${Te6edf3longNameTb4b4b4.Te6edf3anonymizeTffd700}Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ff shortName: Tffd700$Te6edf3shortNameTa5d6ff isLicensed: Tffd700$Te6edf3isLicensedTa5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ff isUnmessagable: Tffd700$Te6edf3isUnmessagableTa5d6ff"Tb4b4b4,
Tb4b4b4)
T8b949e// Also update our own map for our nodeNum, by handling the packet just like packets
T8b949e// from other users
Te6edf3handleReceivedUserTb4b4b4(Te6edf3destTb4b4b4.Te6edf3numTb4b4b4, Te6edf3userTb4b4b4)
T8b949e// encapsulate our payload in the proper protobuf and fire it off
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destTb4b4b4.Te6edf3numTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacketTb4b4b4(Te6edf3id Tff7b72= Te6edf3packetIdTb4b4b4) Tb4b4b4{ Te6edf3setOwner Tff7b72= Te6edf3user Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
T8b949e// Do not use directly, instead call generatePacketId()
Tff7b72private Tff7b72var Te6edf3currentPacketId Tff7b72= Te6edf3RandomTb4b4b4(Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3nextLongTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3absoluteValue
T8b949e/** Generate a unique packet ID (if we know enough to do so - otherwise return 0 so the device will do it) */
Tf0883e@Synchronized
Tff7b72private Tff7b72fun Td2a8ffgeneratePacketIdTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Int Tb4b4b4{
Tff7b72val Te6edf3numPacketIds Tff7b72= Tb4b4b4(Tb4b4b4(T79c0ff1L Te6edf3shl T79c0ff3T79c0ff2Tb4b4b4) Tff7b72- T79c0ff1Tb4b4b4) T8b949e// A mask for only the valid packet ID bits, either 255 or maxint
Te6edf3currentPacketIdTff7b72+Tff7b72+
Te6edf3currentPacketId Tff7b72= Te6edf3currentPacketId Te6edf3and T79c0ff0Te6edf3xffffffff T8b949e// keep from exceeding 32 bits
T8b949e// Use modulus and +1 to ensure we skip 0 on any values we return
Tff7b72return Tb4b4b4(Tb4b4b4(Te6edf3currentPacketId Tff7b72% Te6edf3numPacketIdsTb4b4b4) Tff7b72+ T79c0ff1LTb4b4b4)Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffenqueueForSendingTb4b4b4(Te6edf3pTb4b4b4: Te6edf3DataPacketTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3pTb4b4b4.Te6edf3dataType Tff7b72in Te6edf3rememberDataTypeTb4b4b4) Tb4b4b4{
Te6edf3offlineSentPacketsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3pTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffonServiceActionTb4b4b4(Te6edf3actionTb4b4b4: Te6edf3ServiceActionTb4b4b4) Tb4b4b4{
Te6edf3ignoreException Tb4b4b4{
Tff7b72when Tb4b4b4(Te6edf3actionTb4b4b4) Tb4b4b4{
Tff7b72is Te6edf3ServiceActionTb4b4b4.Te6edf3GetDeviceMetadata Tff7b72-Tff7b72> Te6edf3getDeviceMetadataTb4b4b4(Te6edf3actionTb4b4b4.Te6edf3destNumTb4b4b4)
Tff7b72is Te6edf3ServiceActionTb4b4b4.Te6edf3Favorite Tff7b72-Tff7b72> Te6edf3favoriteNodeTb4b4b4(Te6edf3actionTb4b4b4.Te6edf3nodeTb4b4b4)
Tff7b72is Te6edf3ServiceActionTb4b4b4.Te6edf3Ignore Tff7b72-Tff7b72> Te6edf3ignoreNodeTb4b4b4(Te6edf3actionTb4b4b4.Te6edf3nodeTb4b4b4)
Tff7b72is Te6edf3ServiceActionTb4b4b4.Te6edf3Reaction Tff7b72-Tff7b72> Te6edf3sendReactionTb4b4b4(Te6edf3actionTb4b4b4)
Tff7b72is Te6edf3ServiceActionTb4b4b4.Te6edf3AddSharedContact Tff7b72-Tff7b72> Te6edf3importContactTb4b4b4(Te6edf3actionTb4b4b4.Te6edf3contactTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffimportContactTb4b4b4(Te6edf3contactTb4b4b4: Te6edf3AdminProtosTb4b4b4.Te6edf3SharedContactTb4b4b4) Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(Te6edf3newMeshPacketToTb4b4b4(Te6edf3myNodeNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacket Tb4b4b4{ Te6edf3addContact Tff7b72= Te6edf3contact Tb4b4b4}Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Te6edf3handleReceivedUserTb4b4b4(Te6edf3contactTb4b4b4.Te6edf3nodeNumTb4b4b4, Te6edf3contactTb4b4b4.Te6edf3userTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffgetDeviceMetadataTb4b4b4(Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacketTb4b4b4(Te6edf3wantResponse Tff7b72= Tff7b72trueTb4b4b4) Tb4b4b4{ Te6edf3getDeviceMetadataRequest Tff7b72= Tff7b72true Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8fffavoriteNodeTb4b4b4(Te6edf3nodeTb4b4b4: Te6edf3NodeTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3myNodeNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacket Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3isFavoriteTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffremoving node Tffd700${Te6edf3nodeTb4b4b4.Te6edf3numTffd700}Ta5d6ff from favorite listTa5d6ff"Tb4b4b4)
Te6edf3removeFavoriteNode Tff7b72= Te6edf3nodeTb4b4b4.Te6edf3num
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffadding node Tffd700${Te6edf3nodeTb4b4b4.Te6edf3numTffd700}Ta5d6ff to favorite listTa5d6ff"Tb4b4b4)
Te6edf3setFavoriteNode Tff7b72= Te6edf3nodeTb4b4b4.Te6edf3num
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Te6edf3updateNodeInfoTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3numTb4b4b4) Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3isFavorite Tff7b72= Tff7b72!Te6edf3nodeTb4b4b4.Te6edf3isFavorite Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffignoreNodeTb4b4b4(Te6edf3nodeTb4b4b4: Te6edf3NodeTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3myNodeNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacket Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3isIgnoredTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffremoving node Tffd700${Te6edf3nodeTb4b4b4.Te6edf3numTffd700}Ta5d6ff from ignore listTa5d6ff"Tb4b4b4)
Te6edf3removeIgnoredNode Tff7b72= Te6edf3nodeTb4b4b4.Te6edf3num
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffadding node Tffd700${Te6edf3nodeTb4b4b4.Te6edf3numTffd700}Ta5d6ff to ignore listTa5d6ff"Tb4b4b4)
Te6edf3setIgnoredNode Tff7b72= Te6edf3nodeTb4b4b4.Te6edf3num
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Te6edf3updateNodeInfoTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3numTb4b4b4) Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3isIgnored Tff7b72= Tff7b72!Te6edf3nodeTb4b4b4.Te6edf3isIgnored Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffsendReactionTb4b4b4(Te6edf3reactionTb4b4b4: Te6edf3ServiceActionTb4b4b4.Te6edf3ReactionTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
T8b949e// contactKey: unique contact key filter (channel)+(nodeId)
Tff7b72val Te6edf3channel Tff7b72= Te6edf3reactionTb4b4b4.Te6edf3contactKeyTff7b72[T79c0ff0Tff7b72]Tb4b4b4.Te6edf3digitToIntTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3destNum Tff7b72= Te6edf3reactionTb4b4b4.Te6edf3contactKeyTb4b4b4.Te6edf3substringTb4b4b4(T79c0ff1Tb4b4b4)
Tff7b72val Te6edf3packet Tff7b72=
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildMeshPacketTb4b4b4(Te6edf3channel Tff7b72= Te6edf3channelTb4b4b4, Te6edf3priority Tff7b72= Te6edf3MeshPacketTb4b4b4.Te6edf3PriorityTb4b4b4.Te6edf3BACKGROUNDTb4b4b4) Tb4b4b4{
Te6edf3emoji Tff7b72= T79c0ff1
Te6edf3replyId Tff7b72= Te6edf3reactionTb4b4b4.Te6edf3replyId
Te6edf3portnumValue Tff7b72= Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3TEXT_MESSAGE_APP_VALUE
Te6edf3payload Tff7b72= Te6edf3ByteStringTb4b4b4.Te6edf3copyFromTb4b4b4(Te6edf3reactionTb4b4b4.Te6edf3emojiTb4b4b4.Te6edf3encodeToByteArrayTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(Te6edf3packetTb4b4b4) Tb4b4b4{ Te6edf3connectionState Tb4b4b4}
Te6edf3rememberReactionTb4b4b4(Te6edf3packetTb4b4b4.Te6edf3copy Tb4b4b4{ Te6edf3from Tff7b72= Te6edf3myNodeNum Tb4b4b4}Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3_lastAddressTb4b4b4: Te6edf3MutableStateFlowTff7b72<Tffa657String?Tff7b72> Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Tff7b72nullTb4b4b4)
Tff7b72val Te6edf3lastAddressTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657String?Tff7b72>
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3_lastAddressTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72fun Td2a8ffclearDatabasesTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3serviceScopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffClearing nodeDBTa5d6ff"Tb4b4b4)
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3clearNodeDBTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffupdateLastAddressTb4b4b4(Te6edf3deviceAddrTb4b4b4: Tffa657String?Tb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffsetDeviceAddress: Passing through device change to radio service: Tffd700${Te6edf3deviceAddrTb4b4b4.Te6edf3anonymizeTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72when Tb4b4b4(Te6edf3deviceAddrTb4b4b4) Tb4b4b4{
Tff7b72nullTb4b4b4,
Ta5d6ff"Ta5d6ff"Tb4b4b4,
Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffSetDeviceAddress: No previous device address, setting new oneTa5d6ff"Tb4b4b4)
Te6edf3_lastAddressTb4b4b4.Te6edf3value Tff7b72= Te6edf3deviceAddr
Te6edf3meshPrefsTb4b4b4.Te6edf3deviceAddress Tff7b72= Te6edf3deviceAddr
Tb4b4b4}
Te6edf3lastAddressTb4b4b4.Te6edf3valueTb4b4b4,
Te6edf3NO_DEVICE_SELECTEDTb4b4b4,
Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffSetDeviceAddress: Device address is the none or same, ignoringTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72else Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffSetDeviceAddress: Device address changed from Tffd700$Te6edf3lastAddressTa5d6ff to Tffd700$Te6edf3deviceAddrTa5d6ff"Tb4b4b4)
Te6edf3_lastAddressTb4b4b4.Te6edf3value Tff7b72= Te6edf3deviceAddr
Te6edf3meshPrefsTb4b4b4.Te6edf3deviceAddress Tff7b72= Te6edf3deviceAddr
Te6edf3clearDatabasesTb4b4b4(Tb4b4b4)
Te6edf3clearNotificationsTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffclearNotificationsTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3serviceNotificationsTb4b4b4.Te6edf3clearNotificationsTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3binder Tff7b72=
Tff7b72object Tb4b4b4: T56d364IMeshServiceTb4b4b4.Te6edf3StubTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72override Tff7b72fun Td2a8ffsetDeviceAddressTb4b4b4(Te6edf3deviceAddrTb4b4b4: Tffa657String?Tb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffPassing through device change to radio service: Tffd700${Te6edf3deviceAddrTb4b4b4.Te6edf3anonymizeTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3updateLastAddressTb4b4b4(Te6edf3deviceAddrTb4b4b4)
Tff7b72val Te6edf3res Tff7b72= Te6edf3radioInterfaceServiceTb4b4b4.Te6edf3setDeviceAddressTb4b4b4(Te6edf3deviceAddrTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3resTb4b4b4) Tb4b4b4{
Te6edf3discardNodeDBTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3serviceBroadcastsTb4b4b4.Te6edf3broadcastConnectionTb4b4b4(Tb4b4b4)
Tb4b4b4}
Te6edf3res
Tb4b4b4}
T8b949e// Note: bound methods don't get properly exception caught/logged, so do that with a
T8b949e// wrapper
T8b949e// per https://blog.classycode.com/dealing-with-exceptions-in-aidl-9ba904c6d63
Tff7b72override Tff7b72fun Td2a8ffsubscribeReceiverTb4b4b4(Te6edf3packageNameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3receiverNameTb4b4b4: Tffa657StringTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3clientPackagesTff7b72[Te6edf3receiverNameTff7b72] Tff7b72= Te6edf3packageName
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffgetUpdateStatusTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Int Tff7b72= Tff7b72-T79c0ff4 T8b949e// ProgressNotStarted
Tff7b72override Tff7b72fun Td2a8ffstartFirmwareUpdateTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
T8b949e// TODO reimplement this after we have a new firmware update mechanism
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffgetMyNodeInfoTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3MyNodeInfo? Tff7b72= Tff7b72thisTf0883e@MeshService.myNodeInfoTff7b72?.Te6edf3toMyNodeInfoTb4b4b4(Tb4b4b4)
Tff7b72override Tff7b72fun Td2a8ffgetMyIdTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{ Te6edf3myNodeID Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffgetPacketIdTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{ Te6edf3generatePacketIdTb4b4b4(Tb4b4b4) Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffsetOwnerTb4b4b4(Te6edf3userTb4b4b4: Te6edf3MeshUserTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3setOwnerTb4b4b4(
Te6edf3generatePacketIdTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3user Tb4b4b4{
Te6edf3id Tff7b72= Te6edf3userTb4b4b4.Te6edf3id
Te6edf3longName Tff7b72= Te6edf3userTb4b4b4.Te6edf3longName
Te6edf3shortName Tff7b72= Te6edf3userTb4b4b4.Te6edf3shortName
Te6edf3isLicensed Tff7b72= Te6edf3userTb4b4b4.Te6edf3isLicensed
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffsetRemoteOwnerTb4b4b4(Te6edf3idTb4b4b4: Tffa657IntTb4b4b4, Te6edf3payloadTb4b4b4: Te6edf3ByteArrayTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Tff7b72val Te6edf3parsed Tff7b72= Te6edf3MeshProtosTb4b4b4.Te6edf3UserTb4b4b4.Te6edf3parseFromTb4b4b4(Te6edf3payloadTb4b4b4)
Te6edf3setOwnerTb4b4b4(Te6edf3idTb4b4b4, Te6edf3parsedTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffgetRemoteOwnerTb4b4b4(Te6edf3idTb4b4b4: Tffa657IntTb4b4b4, Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacketTb4b4b4(Te6edf3id Tff7b72= Te6edf3idTb4b4b4, Te6edf3wantResponse Tff7b72= Tff7b72trueTb4b4b4) Tb4b4b4{ Te6edf3getOwnerRequest Tff7b72= Tff7b72true Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffsendTb4b4b4(Te6edf3pTb4b4b4: Te6edf3DataPacketTb4b4b4) Tb4b4b4{
Te6edf3toRemoteExceptions Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3pTb4b4b4.Te6edf3id Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Te6edf3pTb4b4b4.Te6edf3id Tff7b72= Te6edf3generatePacketIdTb4b4b4(Tb4b4b4)
Te6edf3infoTb4b4b4(
Ta5d6ff"Ta5d6ffsendData dest=Tffd700${Te6edf3pTb4b4b4.Te6edf3toTffd700}Ta5d6ff, id=Tffd700${Te6edf3pTb4b4b4.Te6edf3idTffd700}Ta5d6ff <- Tffd700${Te6edf3pTb4b4b4.Te6edf3bytesTff7b72!!Tb4b4b4.Te6edf3sizeTffd700}Ta5d6ff bytesTa5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ff (connectionState=Tffd700$Te6edf3connectionStateTa5d6ff)Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3pTb4b4b4.Te6edf3dataType Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72throw Te6edf3ExceptionTb4b4b4(Ta5d6ff"Ta5d6ffPort numbers must be non-zero!Ta5d6ff"Tb4b4b4) T8b949e// we are now more strict
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3pTb4b4b4.Te6edf3bytesTb4b4b4.Te6edf3size Tff7b72>Tff7b72= Te6edf3MeshProtosTb4b4b4.Te6edf3ConstantsTb4b4b4.Te6edf3DATA_PAYLOAD_LENTb4b4b4.Te6edf3numberTb4b4b4) Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3status Tff7b72= Te6edf3MessageStatusTb4b4b4.Te6edf3ERROR
Tff7b72throw Te6edf3RemoteExceptionTb4b4b4(Ta5d6ff"Ta5d6ffMessage too longTa5d6ff"Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3status Tff7b72= Te6edf3MessageStatusTb4b4b4.Te6edf3QUEUED
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3connectionState Tff7b72=Tff7b72= Te6edf3ConnectionStateTb4b4b4.Te6edf3CONNECTEDTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
Te6edf3sendNowTb4b4b4(Te6edf3pTb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3exTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Te6edf3errormsgTb4b4b4(Ta5d6ff"Ta5d6ffError sending message, so enqueueingTa5d6ff"Tb4b4b4, Te6edf3exTb4b4b4)
Te6edf3enqueueForSendingTb4b4b4(Te6edf3pTb4b4b4)
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3enqueueForSendingTb4b4b4(Te6edf3pTb4b4b4)
Tb4b4b4}
Te6edf3serviceBroadcastsTb4b4b4.Te6edf3broadcastMessageStatusTb4b4b4(Te6edf3pTb4b4b4)
T8b949e// Keep a record of DataPackets, so GUIs can show proper chat history
Te6edf3rememberDataPacketTb4b4b4(Te6edf3pTb4b4b4, Tff7b72falseTb4b4b4)
Te6edf3GeeksvilleApplicationTb4b4b4.Te6edf3analyticsTb4b4b4.Te6edf3trackTb4b4b4(
Ta5d6ff"Ta5d6ffdata_sendTa5d6ff"Tb4b4b4,
Te6edf3DataPairTb4b4b4(Ta5d6ff"Ta5d6ffnum_bytesTa5d6ff"Tb4b4b4, Te6edf3pTb4b4b4.Te6edf3bytesTb4b4b4.Te6edf3sizeTb4b4b4)Tb4b4b4,
Te6edf3DataPairTb4b4b4(Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4, Te6edf3pTb4b4b4.Te6edf3dataTypeTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3GeeksvilleApplicationTb4b4b4.Te6edf3analyticsTb4b4b4.Te6edf3trackTb4b4b4(Ta5d6ff"Ta5d6ffnum_data_sentTa5d6ff"Tb4b4b4, Te6edf3DataPairTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffgetConfigTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3ByteArray Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Tff7b72thisTf0883e@MeshService.localConfig.toByteArrayTb4b4b4(Tb4b4b4) Tff7b72?: Tff7b72throw Te6edf3NoDeviceConfigExceptionTb4b4b4(Tb4b4b4)
Tb4b4b4}
T8b949e/** Send our current radio config to the device */
Tff7b72override Tff7b72fun Td2a8ffsetConfigTb4b4b4(Te6edf3payloadTb4b4b4: Te6edf3ByteArrayTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3setRemoteConfigTb4b4b4(Te6edf3generatePacketIdTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3myNodeNumTb4b4b4, Te6edf3payloadTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffsetRemoteConfigTb4b4b4(Te6edf3idTb4b4b4: Tffa657IntTb4b4b4, Te6edf3numTb4b4b4: Tffa657IntTb4b4b4, Te6edf3payloadTb4b4b4: Te6edf3ByteArrayTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffSetting new radio config!Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3config Tff7b72= Te6edf3ConfigProtosTb4b4b4.Te6edf3ConfigTb4b4b4.Te6edf3parseFromTb4b4b4(Te6edf3payloadTb4b4b4)
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(Te6edf3newMeshPacketToTb4b4b4(Te6edf3numTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacketTb4b4b4(Te6edf3id Tff7b72= Te6edf3idTb4b4b4) Tb4b4b4{ Te6edf3setConfig Tff7b72= Te6edf3config Tb4b4b4}Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3num Tff7b72=Tff7b72= Te6edf3myNodeNumTb4b4b4) Te6edf3setLocalConfigTb4b4b4(Te6edf3configTb4b4b4) T8b949e// Update our local copy
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffgetRemoteConfigTb4b4b4(Te6edf3idTb4b4b4: Tffa657IntTb4b4b4, Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3configTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacketTb4b4b4(Te6edf3id Tff7b72= Te6edf3idTb4b4b4, Te6edf3wantResponse Tff7b72= Tff7b72trueTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3config Tff7b72=Tff7b72= Te6edf3AdminProtosTb4b4b4.Te6edf3AdminMessageTb4b4b4.Te6edf3ConfigTypeTb4b4b4.Te6edf3SESSIONKEY_CONFIG_VALUETb4b4b4) Tb4b4b4{
Te6edf3getDeviceMetadataRequest Tff7b72= Tff7b72true
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3getConfigRequestValue Tff7b72= Te6edf3config
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
T8b949e/** Send our current module config to the device */
Tff7b72override Tff7b72fun Td2a8ffsetModuleConfigTb4b4b4(Te6edf3idTb4b4b4: Tffa657IntTb4b4b4, Te6edf3numTb4b4b4: Tffa657IntTb4b4b4, Te6edf3payloadTb4b4b4: Te6edf3ByteArrayTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffSetting new module config!Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3config Tff7b72= Te6edf3ModuleConfigProtosTb4b4b4.Te6edf3ModuleConfigTb4b4b4.Te6edf3parseFromTb4b4b4(Te6edf3payloadTb4b4b4)
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(Te6edf3newMeshPacketToTb4b4b4(Te6edf3numTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacketTb4b4b4(Te6edf3id Tff7b72= Te6edf3idTb4b4b4) Tb4b4b4{ Te6edf3setModuleConfig Tff7b72= Te6edf3config Tb4b4b4}Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3num Tff7b72=Tff7b72= Te6edf3myNodeNumTb4b4b4) Te6edf3setLocalModuleConfigTb4b4b4(Te6edf3configTb4b4b4) T8b949e// Update our local copy
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffgetModuleConfigTb4b4b4(Te6edf3idTb4b4b4: Tffa657IntTb4b4b4, Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3configTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacketTb4b4b4(Te6edf3id Tff7b72= Te6edf3idTb4b4b4, Te6edf3wantResponse Tff7b72= Tff7b72trueTb4b4b4) Tb4b4b4{
Te6edf3getModuleConfigRequestValue Tff7b72= Te6edf3config
Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffsetRingtoneTb4b4b4(Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3ringtoneTb4b4b4: Tffa657StringTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacket Tb4b4b4{ Te6edf3setRingtoneMessage Tff7b72= Te6edf3ringtone Tb4b4b4}Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffgetRingtoneTb4b4b4(Te6edf3idTb4b4b4: Tffa657IntTb4b4b4, Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacketTb4b4b4(Te6edf3id Tff7b72= Te6edf3idTb4b4b4, Te6edf3wantResponse Tff7b72= Tff7b72trueTb4b4b4) Tb4b4b4{
Te6edf3getRingtoneRequest Tff7b72= Tff7b72true
Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffsetCannedMessagesTb4b4b4(Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3messagesTb4b4b4: Tffa657StringTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacket Tb4b4b4{ Te6edf3setCannedMessageModuleMessages Tff7b72= Te6edf3messages Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffgetCannedMessagesTb4b4b4(Te6edf3idTb4b4b4: Tffa657IntTb4b4b4, Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacketTb4b4b4(Te6edf3id Tff7b72= Te6edf3idTb4b4b4, Te6edf3wantResponse Tff7b72= Tff7b72trueTb4b4b4) Tb4b4b4{
Te6edf3getCannedMessageModuleMessagesRequest Tff7b72= Tff7b72true
Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffsetChannelTb4b4b4(Te6edf3payloadTb4b4b4: Te6edf3ByteArray?Tb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3setRemoteChannelTb4b4b4(Te6edf3generatePacketIdTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3myNodeNumTb4b4b4, Te6edf3payloadTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffsetRemoteChannelTb4b4b4(Te6edf3idTb4b4b4: Tffa657IntTb4b4b4, Te6edf3numTb4b4b4: Tffa657IntTb4b4b4, Te6edf3payloadTb4b4b4: Te6edf3ByteArray?Tb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Tff7b72val Te6edf3channel Tff7b72= Te6edf3ChannelProtosTb4b4b4.Te6edf3ChannelTb4b4b4.Te6edf3parseFromTb4b4b4(Te6edf3payloadTb4b4b4)
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(Te6edf3newMeshPacketToTb4b4b4(Te6edf3numTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacketTb4b4b4(Te6edf3id Tff7b72= Te6edf3idTb4b4b4) Tb4b4b4{ Te6edf3setChannel Tff7b72= Te6edf3channel Tb4b4b4}Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffgetRemoteChannelTb4b4b4(Te6edf3idTb4b4b4: Tffa657IntTb4b4b4, Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3indexTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacketTb4b4b4(Te6edf3id Tff7b72= Te6edf3idTb4b4b4, Te6edf3wantResponse Tff7b72= Tff7b72trueTb4b4b4) Tb4b4b4{
Te6edf3getChannelRequest Tff7b72= Te6edf3index Tff7b72+ T79c0ff1
Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffbeginEditSettingsTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(Te6edf3newMeshPacketToTb4b4b4(Te6edf3myNodeNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacket Tb4b4b4{ Te6edf3beginEditSettings Tff7b72= Tff7b72true Tb4b4b4}Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffcommitEditSettingsTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(Te6edf3newMeshPacketToTb4b4b4(Te6edf3myNodeNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacket Tb4b4b4{ Te6edf3commitEditSettings Tff7b72= Tff7b72true Tb4b4b4}Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffgetChannelSetTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3ByteArray Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{ Tff7b72thisTf0883e@MeshService.channelSet.toByteArrayTb4b4b4(Tb4b4b4) Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffgetNodesTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3MutableListTff7b72<Te6edf3NodeInfoTff7b72> Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Tff7b72val Te6edf3r Tff7b72= Te6edf3nodeDBbyNodeNumTb4b4b4.Te6edf3valuesTb4b4b4.Te6edf3map Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3toNodeInfoTb4b4b4(Tb4b4b4) Tb4b4b4}Tb4b4b4.Te6edf3toMutableListTb4b4b4(Tb4b4b4)
Te6edf3infoTb4b4b4(Ta5d6ff"Ta5d6ffin getOnline, count=Tffd700${Te6edf3rTb4b4b4.Te6edf3sizeTffd700}Ta5d6ff"Tb4b4b4)
T8b949e// return arrayOf("+16508675309")
Te6edf3r
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffconnectionStateTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657String Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Tff7b72val Te6edf3r Tff7b72= Tff7b72thisTf0883e@MeshService.connectionState
Te6edf3infoTb4b4b4(Ta5d6ff"Ta5d6ffin connectionState=Tffd700$Te6edf3rTa5d6ff"Tb4b4b4)
Te6edf3rTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffstartProvideLocationTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{ Te6edf3startLocationRequestsTb4b4b4(Tb4b4b4) Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffstopProvideLocationTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{ Te6edf3stopLocationRequestsTb4b4b4(Tb4b4b4) Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffremoveByNodenumTb4b4b4(Te6edf3requestIdTb4b4b4: Tffa657IntTb4b4b4, Te6edf3nodeNumTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3nodeDBbyNodeNumTb4b4b4.Te6edf3removeTb4b4b4(Te6edf3nodeNumTb4b4b4)
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(Te6edf3newMeshPacketToTb4b4b4(Te6edf3myNodeNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacket Tb4b4b4{ Te6edf3removeByNodenum Tff7b72= Te6edf3nodeNum Tb4b4b4}Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffrequestUserInfoTb4b4b4(Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3destNum Tff7b72!Tff7b72= Te6edf3myNodeNumTb4b4b4) Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildMeshPacketTb4b4b4(Te6edf3channel Tff7b72= Te6edf3nodeDBbyNodeNumTff7b72[Te6edf3destNumTff7b72]Tff7b72?.Te6edf3channel Tff7b72?: T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3portnumValue Tff7b72= Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3NODEINFO_APP_VALUE
Te6edf3wantResponse Tff7b72= Tff7b72true
Te6edf3payload Tff7b72= Te6edf3nodeDBbyNodeNumTff7b72[Te6edf3myNodeNumTff7b72]Tff7b72!!Tb4b4b4.Te6edf3userTb4b4b4.Te6edf3toByteStringTb4b4b4(Tb4b4b4)
Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffrequestPositionTb4b4b4(Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3positionTb4b4b4: Te6edf3PositionTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3destNum Tff7b72!Tff7b72= Te6edf3myNodeNumTb4b4b4) Tb4b4b4{
T8b949e// Determine the best position to send based on user preferences and available
T8b949e// data
Tff7b72val Te6edf3provideLocation Tff7b72= Te6edf3meshPrefsTb4b4b4.Te6edf3shouldProvideNodeLocationTb4b4b4(Te6edf3myNodeNumTb4b4b4)
Tff7b72val Te6edf3currentPosition Tff7b72=
Tff7b72when Tb4b4b4{
T8b949e// Use provided position if valid and user allows phone location sharing
Te6edf3provideLocation Tff7b72&Tff7b72& Te6edf3positionTb4b4b4.Te6edf3isValidTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Te6edf3position
T8b949e// Otherwise use the last valid position from nodeDB (node GPS or
T8b949e// static)
Tff7b72else Tff7b72-Tff7b72> Te6edf3nodeDBbyNodeNumTff7b72[Te6edf3myNodeNumTff7b72]Tff7b72?.Te6edf3positionTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3PositionTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}Tff7b72?.Te6edf3takeIf Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3isValidTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3currentPosition Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3debugTb4b4b4(Ta5d6ff"Ta5d6ffPosition request skipped - no valid position availableTa5d6ff"Tb4b4b4)
Tff7b72returnTf0883e@toRemoteExceptions
Tb4b4b4}
T8b949e// Convert Position to MeshProtos.Position for the payload
Tff7b72val Te6edf3meshPosition Tff7b72= Te6edf3position Tb4b4b4{
Te6edf3latitudeI Tff7b72= Te6edf3PositionTb4b4b4.Te6edf3degITb4b4b4(Te6edf3currentPositionTb4b4b4.Te6edf3latitudeTb4b4b4)
Te6edf3longitudeI Tff7b72= Te6edf3PositionTb4b4b4.Te6edf3degITb4b4b4(Te6edf3currentPositionTb4b4b4.Te6edf3longitudeTb4b4b4)
Te6edf3altitude Tff7b72= Te6edf3currentPositionTb4b4b4.Te6edf3altitude
Te6edf3time Tff7b72= Te6edf3currentSecondTb4b4b4(Tb4b4b4)
Tb4b4b4}
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildMeshPacketTb4b4b4(
Te6edf3channel Tff7b72= Te6edf3nodeDBbyNodeNumTff7b72[Te6edf3destNumTff7b72]Tff7b72?.Te6edf3channel Tff7b72?: T79c0ff0Tb4b4b4,
Te6edf3priority Tff7b72= Te6edf3MeshPacketTb4b4b4.Te6edf3PriorityTb4b4b4.Te6edf3BACKGROUNDTb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3portnumValue Tff7b72= Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3POSITION_APP_VALUE
Te6edf3payload Tff7b72= Te6edf3meshPositionTb4b4b4.Te6edf3toByteStringTb4b4b4(Tb4b4b4)
Te6edf3wantResponse Tff7b72= Tff7b72true
Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffsetFixedPositionTb4b4b4(Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3positionTb4b4b4: Te6edf3PositionTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Tff7b72val Te6edf3pos Tff7b72= Te6edf3position Tb4b4b4{
Te6edf3latitudeI Tff7b72= Te6edf3PositionTb4b4b4.Te6edf3degITb4b4b4(Te6edf3positionTb4b4b4.Te6edf3latitudeTb4b4b4)
Te6edf3longitudeI Tff7b72= Te6edf3PositionTb4b4b4.Te6edf3degITb4b4b4(Te6edf3positionTb4b4b4.Te6edf3longitudeTb4b4b4)
Te6edf3altitude Tff7b72= Te6edf3positionTb4b4b4.Te6edf3altitude
Tb4b4b4}
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacket Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3position Tff7b72!Tff7b72= Te6edf3PositionTb4b4b4(T79c0ff0.0Tb4b4b4, T79c0ff0.0Tb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3setFixedPosition Tff7b72= Te6edf3pos
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3removeFixedPosition Tff7b72= Tff7b72true
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Te6edf3updateNodeInfoTb4b4b4(Te6edf3destNumTb4b4b4) Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3setPositionTb4b4b4(Te6edf3posTb4b4b4, Te6edf3currentSecondTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffrequestTracerouteTb4b4b4(Te6edf3requestIdTb4b4b4: Tffa657IntTb4b4b4, Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3tracerouteStartTimesTff7b72[Te6edf3requestIdTff7b72] Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildMeshPacketTb4b4b4(
Te6edf3wantAck Tff7b72= Tff7b72trueTb4b4b4,
Te6edf3id Tff7b72= Te6edf3requestIdTb4b4b4,
Te6edf3channel Tff7b72= Te6edf3nodeDBbyNodeNumTff7b72[Te6edf3destNumTff7b72]Tff7b72?.Te6edf3channel Tff7b72?: T79c0ff0Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3portnumValue Tff7b72= Te6edf3PortnumsTb4b4b4.Te6edf3PortNumTb4b4b4.Te6edf3TRACEROUTE_APP_VALUE
Te6edf3wantResponse Tff7b72= Tff7b72true
Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffrequestShutdownTb4b4b4(Te6edf3requestIdTb4b4b4: Tffa657IntTb4b4b4, Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacketTb4b4b4(Te6edf3id Tff7b72= Te6edf3requestIdTb4b4b4) Tb4b4b4{ Te6edf3shutdownSeconds Tff7b72= T79c0ff5 Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffrequestRebootTb4b4b4(Te6edf3requestIdTb4b4b4: Tffa657IntTb4b4b4, Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacketTb4b4b4(Te6edf3id Tff7b72= Te6edf3requestIdTb4b4b4) Tb4b4b4{ Te6edf3rebootSeconds Tff7b72= T79c0ff5 Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffrequestFactoryResetTb4b4b4(Te6edf3requestIdTb4b4b4: Tffa657IntTb4b4b4, Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacketTb4b4b4(Te6edf3id Tff7b72= Te6edf3requestIdTb4b4b4) Tb4b4b4{ Te6edf3factoryResetDevice Tff7b72= T79c0ff1 Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffrequestNodedbResetTb4b4b4(Te6edf3requestIdTb4b4b4: Tffa657IntTb4b4b4, Te6edf3destNumTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Te6edf3toRemoteExceptions Tb4b4b4{
Te6edf3packetHandlerTb4b4b4.Te6edf3sendToRadioTb4b4b4(
Te6edf3newMeshPacketToTb4b4b4(Te6edf3destNumTb4b4b4)Tb4b4b4.Te6edf3buildAdminPacketTb4b4b4(Te6edf3id Tff7b72= Te6edf3requestIdTb4b4b4) Tb4b4b4{ Te6edf3nodedbReset Tff7b72= T79c0ff1 Tb4b4b4}Tb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3connectionState
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.54s